m0_46660886
小渣飞、
采纳率50%
2020-12-21 15:07 阅读 25
已采纳

Java 中多线程同步布尔值的问题?

 

找了一天的 Bug 还是找不到是那个地方出了问题,目前线程2卡死,原因是布尔值不同步,可是我使用 static 关键字了,请问为什么在线程1设置为 true 后,线程2还是false,求解决思路

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;


public class ThreadCopy {
    private static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
    private static final Scanner scanner = new Scanner(System.in);
    public static String[] types;
    public static File workPath;
    public static File savePath;
    public static int copyErrorCount;
    public static int copySuccessCount;
    public static boolean isFlag = false;

    public static void main(String[] args) throws InterruptedException {

        System.out.println("请输入一个工作路径:");
        workPath = new File(scanner.nextLine());
        System.out.println("请输入一个存储路径:");
        savePath = new File("/Users/jeffrey/test/test2");
        System.out.println("请输入筛选文件的类型,如有多个使用逗号隔开:");
        types = scanner.nextLine().replace(" ", "").split(",");


        if (workPath.exists() && savePath.exists()) {
            Thread t1 = new Thread(new ThreadForFindFile(queue, workPath, types));
            isFlag = true;

            Thread t2 = new Thread(new ThreadForCopyFile(queue, savePath));
            t1.start();
            t2.start();

            while (true) {

                if (!t1.isAlive()) {
                    isFlag = true;
                }
                
                if (!t1.isAlive() && !t2.isAlive()){
                    System.out.println("程序结束");
                    break;
                }
            }

        } else {
            throw new RuntimeException("请输入有效地工作路径或存储路径");
        }
    }
}

class ThreadForFindFile extends Thread {

    private final ConcurrentLinkedQueue<String> queue;
    private final File srcPath;
    private final String[] fileTypes;

    public ThreadForFindFile(ConcurrentLinkedQueue<String> queue, File srcPath, String[] fileTypes) {
        this.queue = queue;
        this.srcPath = srcPath;
        this.fileTypes = fileTypes;
    }

    @Override
    public void run() {
        find(this.srcPath);
    }

    private void find(File srcPath) {
        File[] files = srcPath.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    find(file);
                } else {
                    String[] split = file.toString().split(File.separator);
                    String[] suffix = split[split.length - 1].split("\\.");
                    if (Arrays.toString(fileTypes).contains(suffix[suffix.length - 1])) {
                        this.queue.add(file.toString());
                    }
                }
            }
        }
    }
}

class ThreadForCopyFile extends Thread {
    public static int copyErrorCount = ThreadCopy.copyErrorCount;
    public static int copySuccessCount = ThreadCopy.copySuccessCount;
    public static boolean ThreadOneIsAlive = ThreadCopy.isFlag;

    private final ConcurrentLinkedQueue<String> queue;
    private final File savePath;

    public ThreadForCopyFile(ConcurrentLinkedQueue<String> queue, File savePath) {
        this.queue = queue;
        this.savePath = savePath;
    }

    @Override
    public void run() {
        System.out.println(ThreadOneIsAlive);

        while (!ThreadOneIsAlive) {
            String file = queue.poll();
            try {
                if (file != null) {
                    String[] split = file.split(File.separator);
                    String name = split[split.length - 1];
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(savePath + File.separator + name));
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len = bis.read(bytes)) != -1) {
                        bos.write(bytes, 0, len);
                    }
                    copySuccessCount++;
                }

            } catch (Exception e) {
                copyErrorCount++;
                e.printStackTrace();
                break;
            }

        }

    }
}


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

3条回答 默认 最新

  • 已采纳
    qq_29240707 根由心生 2020-12-21 16:56
    14 public static  boolean isFlag = true;
    
    
      34          while (true) {
                    if (!t1.isAlive() && !t2.isAlive()){
                        System.out.println("程序结束");
                        break;
                    }
                }
    
    84  ThreadCopy.isFlag = false;
    
    104  while (ThreadCopy.isFlag || !queue.isEmpty() )

    看了下 你想做的是 一个线程找文件 一个线程复制文件吧   对着行号 改掉就行了

     

     

     

     

    点赞 1 评论 复制链接分享
  • xionglangs 编程爱好者熊浪 2020-12-21 17:54

    每个线程都有一份自己的本地变量,你的多线程连可见性都保证不了,还有原子性,volatile可以保证可见性,看看你的代码需不需要保证原子性,如果不需要,加上volatile就可以了。

    点赞 1 评论 复制链接分享
  • m0_46660886 小渣飞、 2020-12-21 19:38

    感谢回答,才想起来我在这里发问了,这是我的解决方式

    点赞 评论 复制链接分享

相关推荐