Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程始终在运行,可以';停不下来_Java - Fatal编程技术网

Java 线程始终在运行,可以';停不下来

Java 线程始终在运行,可以';停不下来,java,Java,我想做一个测试,两个线程,一个线程正在更改值,另一个线程等待第一个线程,然后中断并完成。但问题是等待的线程总是在运行,不能再停止。另一个问题是,当我打开“System.out.println(i+“run”);”的代码时,所有线程都可以正常工作,这太奇怪了 import java.util.Date; public class ThreadTestTwo { public int a = 0, b = 0,c = 0; public static void main(String[]

我想做一个测试,两个线程,一个线程正在更改值,另一个线程等待第一个线程,然后中断并完成。但问题是等待的线程总是在运行,不能再停止。另一个问题是,当我打开“System.out.println(i+“run”);”的代码时,所有线程都可以正常工作,这太奇怪了

import java.util.Date;

public class ThreadTestTwo {
    public int a = 0, b = 0,c = 0;

public static void main(String[] args) {
    System.out.println(new Date()+"start");
    for (int i = 0; i < 100000; i++) {
        new ThreadTestTwo().start(i);
        if(i % 100000 == 0){
            System.out.println(i/100000);
        }
    }
    System.out.println(new Date()+"finish");
}

public void start(final int i){
    Thread readThread = new Thread(){
        @Override
        public void run() {
            while (true) {
                if(c == 1){
                    b = a;
//                      System.out.println(i+", set b "+a);
                    break;
                }
//                  System.out.println(i + " run");
            }
        }
    };
    Thread writeThread = new Thread(){
        @Override
        public void run() {
            a = 1;
            c = 1;
        }
    };
    writeThread.setName("mywrite");
    readThread.setName("myread");
    System.out.println(i+" start");
    writeThread.start();
    readThread.start();

    try {
        writeThread.join();
        readThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(i+" end");
    if(b != 1)
        throw new RuntimeException("b = "+b);
}

}
import java.util.Date;
公共类ThreadTest2{
公共整数a=0,b=0,c=0;
公共静态void main(字符串[]args){
System.out.println(新日期()+“开始”);
对于(int i=0;i<100000;i++){
新的ThreadTestTwo().start(i);
如果(i%100000==0){
系统输出打印项次(i/100000);
}
}
System.out.println(新日期()+“完成”);
}
公共作废开始(最终int i){
线程readThread=新线程(){
@凌驾
公开募捐{
while(true){
如果(c==1){
b=a;
//系统输出打印项次(i+),设置b“+a);
打破
}
//System.out.println(i+“run”);
}
}
};
线程writeThread=新线程(){
@凌驾
公开募捐{
a=1;
c=1;
}
};
writeThread.setName(“mywrite”);
setName(“myread”);
System.out.println(i+“开始”);
writeThread.start();
readThread.start();
试一试{
writeThread.join();
readThread.join();
}捕捉(中断异常e){
e、 printStackTrace();
}
系统输出打印项次(i+“结束”);
如果(b!=1)
抛出新的运行时异常(“b=“+b”);
}
}

在线程之间使用简单的int作为信号不是一个好主意,因为它不是线程安全的


因此,请尝试改用AtomicInteger,或者将int设置为volatile,看看会发生什么情况。

除非变量标记为volatile,或者需要使用同步或显式锁定来处理事务,否则不能保证在另一个线程中看到一个线程的写入操作。

在您的例子中,a、b、c是多个线程访问的实例变量,读线程缓存这些值,因此它看不到写入线程的刷新值

有关更多详细信息,请参阅以下链接:
我建议您阅读更多关于线程的内容。这是一份来自O'Realy的有趣文件:

至于您的实现,您应该知道线程对一个变量的修改可能不会被读线程看到。要解决此问题,请使用
synchronized
获取和设置,访问同步块中的变量,或使用
AtomicReference
。您还可以使用
,例如
ReantrantLock

另外,如果您有两个线程,其中第一个线程正在等待第二个线程的输入,那么您可以在
synchronized
块中为第一个线程使用
wait()
,以便第二个线程在完成其工作时可以
notify()
第一个线程

大概是这样的:

import java.util.Date;
公共类ThreadTest2{
私有整数a=0,b=0,c=0;
私有最终对象锁=新对象();
//任何物体都像锁一样好,对于这样一个简单的例子来说都可以。
//此对象将用作同步块的监视器。
公共作废开始(最终int i){
线程readThread=新线程(){
@凌驾
公开募捐{
已同步(锁定){
试一试{
而(c!=1){
lock.wait();
}
}
捕获(中断异常例外){
//异常处理
}
b=a;
}
//System.out.println(i+“run”);
}
};
线程writeThread=新线程(){
@凌驾
公开募捐{
已同步(锁定){
a=1;
c=1;
lock.notify();
}
}
};
writeThread.setName(“mywrite”);
setName(“myread”);
System.out.println(i+“开始”);
writeThread.start();
readThread.start();
系统输出打印项次(i+“结束”);
}
公共静态void main(字符串[]args){
System.out.println(新日期()+“开始”);
对于(int i=0;i<100000;i++){
新的ThreadTestTwo().start(i);
如果(i%100000==0){
系统输出打印项次(i/100000);
}
}
System.out.println(新日期()+“完成”);
}
}
我想说你不需要用这个方法
join()
。但是如果要在第一个线程完成后等待第二个线程启动,则必须在启动它之前使用
join()
。像这样:

writeThread.start();
试一试{
writeThread.join();
}
捕获(中断异常例外){
//异常处理
}
readThread.start();
试一试{
readThread.join();
}
捕获(中断异常例外){
//异常处理
}
但是如果您在这个特殊情况下使用
join()
,我会说您不需要任何同步的块或条件,因为第二个线程只会在第一个线程死后启动。大概是这样的:

公共作废开始(最终int i){
线程readThread=新线程(){
@凌驾
公开募捐{
b=a;
//System.out.println(i+“run”);
}
};
线程writeThread=新线程(){
@凌驾
公开募捐{
a=1;
c=1;
}
};
setName(“mywrite