在Thread的run()中,条件检查失败

时间:2015-07-09 09:37:37

标签: java multithreading if-statement

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();
    }

}

run()方法中的计数检查不起作用。知道为什么吗?我可以看到,每次调用都会增加计数,但是检查不起作用,每次控件传递给read()方法,并且不会去写()

我做错了什么?另外,还有其他有效的方法从两个线程调用多个方法,具体取决于具体情况吗?

P.S。我试图使用一个线程读取输入,并将输入值写入另一个线程中的文件

6 个答案:

答案 0 :(得分:1)

不要为每一行创建新的BufferedReader。在插座的使用寿命中使用相同的一个。您正在丢失每个BufferedReader预读的数据。

答案 1 :(得分:1)

删除除主要方法之外的所有静态...所有你需要确保的是读写不要改变/读取"计数"同时...使用不同的锁定对象,如" lockObject"并使用wait()和notify()。您正在寻找生产者/消费者类型的模式。以下是一个示例:http://www.programcreek.com/2009/02/notify-and-wait-example/

答案 2 :(得分:1)

试试这个:

    MultiThreadExample th1=new MultiThreadExample();
    MultiThreadExample th2=new MultiThreadExample();
    th1.start();
   try {
    th1.join();
} catch (InterruptedException ex) {
    System.out.println(ex.getMessage());
}
    th2.start();

答案 3 :(得分:1)

也可以尝试类似的'做法。 ,哪个线程进入第一次读取,后一个等待前者读取然后写入。 (它不需要你的静态方法同步)

Use following code it might be work because in my case it's working.



<i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding WindowLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

ViewModel.cs,



   public ICommand WindowLoadedCommand
    {
        get { return new RelayCommand<object>(WindowLoadedCommandExecute); }

    }
    public void WindowLoadedCommandExecute(object obj)
    {

    }

答案 4 :(得分:1)

  

好的,你可以向我解释一下,为什么我之前的代码无效,检查失败了吗?

@ Shail016在对你的问题的评论中解释了这一点。这是一个可能的事件序列。

主线程调用th1.start(),调用th2.start(),然后退出。

主题1进入run()方法,看到计数== 0,输入read()方法,调用System.out.println(...)

线程2进入run()方法,看到count == 0,尝试输入read()方法,被阻止,等待互斥锁。

线程1从System.out.println(...)调用返回,读取一行,递增count,然后返回,

允许线程2进入read()等等,

答案 5 :(得分:0)

count标记为易变。这可确保其他线程可以看到来自一个线程的更改。只要只有一个主题更新count,就可以了,否则,您可以使用AtomicIntegerAtomicIntegerFieldUpdater和volatile字段,或者(如果您测量高争用,在您的情况下不太可能)LongAdder(所有类都来自java.util.concurrent.atomic包,最后一个只在Java 8中可用。)