Java 在线程的run()中条件检查失败
run()方法中的计数检查无效。知道为什么吗?我可以看到,每次调用计数都会增加,但检查不起作用,每次控件传递到read()方法,而不是write()时 我做错了什么?另外,根据具体情况,是否有其他有效的方法从两个线程调用多个方法Java 在线程的run()中条件检查失败,java,multithreading,if-statement,Java,Multithreading,If Statement,run()方法中的计数检查无效。知道为什么吗?我可以看到,每次调用计数都会增加,但检查不起作用,每次控件传递到read()方法,而不是write()时 我做错了什么?另外,根据具体情况,是否有其他有效的方法从两个线程调用多个方法 另外,我正在尝试使用一个线程读取输入,并将输入值写入另一个线程中的文件不要为每一行创建新的BufferedReader。在插座的使用寿命内使用相同的插座。每个BufferedReader读取的数据都将丢失。请删除除主方法外的所有静态数据。。。您需要确保的是读和写不会同时
另外,我正在尝试使用一个线程读取输入,并将输入值写入另一个线程中的文件不要为每一行创建新的
BufferedReader
。在插座的使用寿命内使用相同的插座。每个BufferedReader
读取的数据都将丢失。请删除除主方法外的所有静态数据。。。您需要确保的是读和写不会同时更改/读取“计数”。。。使用不同的锁对象,如“lockObject”,并使用wait()和notify()。你在这里寻找一种生产者/消费者模式。下面是一个例子:试试这个:
public class MultiThreadExample extends Thread {
public static int count=0;
static String s="";
synchronized public static String read(){
String line="";
System.out.println("Enter new line:");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
try {
line=br.readLine();
count++;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return line;
}
synchronized public static void write(String line){
try {
BufferedWriter br=new BufferedWriter(new FileWriter("C://name.txt"));
br.write(line);
System.out.println(line);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run(){
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
th2.start();
}
}
将
count
标记为volatile。这确保了其他线程可以看到来自一个线程的更改。只要只有一个线程更新count
,这就可以了,否则,您可以将AtomicInteger
、AtomicIntegerFieldDupDater与易失性字段结合使用,或者(如果您测量到高争用,在您的情况下不太可能)使用LongAdder
(所有类都来自java.util.concurrent.atomic
包,最后一个仅在java 8中可用)。也可以尝试“类似”的方法,任何线程都先进入读取,而后者等待前者读取,然后再写入。(不需要同步静态方法)
好的,你能给我解释一下,为什么我以前的代码不起作用,而检查失败了 @Shail016在对你的问题的评论中解释了这一点。下面是一个可能的事件序列 主线程调用
th1.start()
,调用th2.start()
,然后退出
线程1进入run()
方法,看到count==0,进入read()
方法,调用System.out.println(…)
线程2进入run()
方法,看到count==0,尝试进入read()
方法,被阻塞,等待互斥锁
线程1从System.out.println(…)
调用返回,读取一行,增加计数,然后返回
允许线程2进入读取()
,等等
等等
等。好的,但这是另一个问题,if(count==0)条件检查失败。知道原因吗?解决后,我将更改BufferedReader行尝试如下声明计数:public volatile static int count=0;不,它仍然不起作用..:(@Win.ubuntu-这根本不是必需的。同步块/方法确保在存在之前发生。即使您添加volatile
,JIT也很可能只是为您删除/忽略它。因为您的条件(即计数读取)不是线程安全的,线程可以在以下情况下执行(计数==0),读取相同的值0,然后等待阻止读线调用。如果您的目的是让一个线程读取,另一个线程写入,则需要一个信号机制,如Object.wait and notify……或者您需要足够快,以便在第二个线程检查条件之前向第一个线程提供输入。:)你好,@Shail016,你能发布你刚刚给出并删除的答案吗?想看看你在那里做了什么。:)仍然不起作用。。结果相同,只是因为睡眠的原因有延迟()好的,你能给我解释一下,为什么我以前的代码不起作用,而检查失败了吗?@Shubharti Dasgupta这里有两个线程顺序运行,即th2.run在th1之后执行。run finishesMark count为volatile。这不是必需的。同步可以确保在之前发生。而且,这还不够。问题是访问count
未同步假定“读取器”角色的线程在递增计数之前将执行多个I/O操作。这使另一个线程有足够的机会在递增发生之前测试计数(对计数的访问在测试点不同步)。因此,两个线程都很可能假定为“读取器”角色
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
try {
th1.join();
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
th2.start();
static ReentrantLock l = new ReentrantLock();
public void run(){
l.lock();
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
l.unlock();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}