在下面的代码中,我试图使用多个线程来访问队列,直到isFound = false
。我已将isFound
变量声明为volatile
,并且在某些条件后我将其值更改为true。如果我在一个线程中更改其值,并且根据定义,其更新值应该对所有其他线程可见。运行此代码时,isFound
的值仍为false
。
如果我将isFound从volatile更改为static,它可以正常工作吗?
class FileAccessThread implements Runnable {
volatile boolean isFound = false;
BlockingQueue<String> bq;
public FileAccessThread(BlockingQueue<String> bq) {
this.bq = bq;
}
public void run() {
System.out.println("ifFound "+isFound);
if(bq !=null && !isFound){
try {
System.out.println("Current Thread "+Thread.currentThread().getName());
String filePath = bq.take();
System.out.println("File Path "+filePath);
Thread.sleep(2000);
if(filePath.equals("c:/test/t5.txt")) {
isFound = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MultiFileAccess {
public static void main(String[] args) {
ExecutorService e = Executors.newFixedThreadPool(3);
BlockingQueue<String> bq = new LinkedBlockingQueue<>();
bq.add("c:/test/t1.txt");
bq.add("c:/test/t2.txt");
bq.add("c:/test/t3.txt");
bq.add("c:/test/t4.txt");
bq.add("c:/test/t5.txt");
bq.add("c:/test/t6.txt");
bq.add("c:/test/t7.txt");
bq.add("c:/test/t8.txt");
bq.add("c:/test/t9.txt");
bq.add("c:/test/t10.txt");
int lengthOfQueue = bq.size();
for(int i=0;i < lengthOfQueue-1;i++){
e.execute(new FileAccessThread(bq));
}
e.shutdown();
}
}
答案 0 :(得分:3)
我认为你对static
和volatile
做了什么有误解。
volatile
对变量强加了一组内存读/写语义。在这种情况下,它并不重要,因为您已经使用它自己的变量定义了每个线程,因此每个线程只读取和写入它自己的{{1的本地副本}}
在您将其定义为静态的情况下,所有线程都共享相同的变量 - 因此,如果一个线程更改它,那么其他线程将(可能)看到它。虽然你没有围绕变量进行任何同步,但是关于何时或哪些线程会看到变化是不确定的。
要更深入地了解静态与易失性,请查看此问题的答案:Volatile Vs Static in java
答案 1 :(得分:0)
只需更改实例化Runnable
的方式:
Runnable oneInstanceOnly = new FileAccessThread(bq);
for(int i=0;i < lengthOfQueue-1;i++){
e.execute(oneInstanceOnly);
}
您创建了许多实例,每个实例都有自己的isFound
字段,除非创建为static
。