Thắc mắc về thread trong java


cho mình hỏi là ở thread1 sau khi có giái trị thì mình gọi notifyall xong wait thì nó nhảy sang thread2 xong thread2 lại gọi notifyall cho nó chạy vậy tại sao lại gọi wait ngay sau đó thế thì giá trị ở dưới wait thread2 chạy thế nào ạ ai biết giải thích giúp mình với

1 Like

Hai luồng này chạy và chờ nhau một cách lần lượt.
Kiểu như này:

Thread1 random 3
Thread2 result 9
Thread1 random 4
Thread2 result 16
Thread1 random 7
Thread2 result 49
...

Cho dù luồng nào chạy trước thì trình tự kết quả luôn theo 1 hướng. T1 > T2 > T1 > T2 …
Khi T2 chạy sẽ luôn chờ trước, đó là lý do đoạn mã in kết quả phải nằm sau wait(). Nó sẽ chờ khi T1 tạo ngẫu nhiên xong và báo cho nó.

4 Likes

ơ vậy thì ví dụ thread1 chạy trước thì nó chạy đến wait thì thread2 được chạy xong thread2 chạy đến wait vậy thì nó lại nhảy về thread 1 cho đến khi thread1 chạy đến notifyall() thế thì thread1 mất đi 1 giá trị mới đúng chứ bạn

Mình xét lại thì đúng như bạn đề cập. Mình xin lỗi.
Cách giải quyết là thêm vài điều kiện để quá trình thực hiện được đúng trình tự, thay vì cứ gọi không như vậy.
Bạn tham khảo:

import java.util.Random;


public class Main {
  public static void main(String[] args) {
    System.out.println("Hello world!");
    Test x = new Test(5);
    T1 t1 = new T1(x);
    T2 t2 = new T2(x);
    
    // T1 trước
    t1.start();
    try{
      Thread.sleep(100); // tạo khoảng cách đảm bảo T1 chạy trước
    } catch (Exception ex){}
    t2.start();
    
    /*
    // T2 trước
    t2.start();
    try{
      Thread.sleep(100); // tạo khoảng cách đảm bảo T2 chạy trước
    } catch (Exception ex){}
    t1.start();
    */
  }
  
  static class T1 extends Thread{
    public Test t;
    public T1(Test t){
      this.t = t;
    }
    
    @Override public void run(){
      t.r = true; // T1 đã chạy
      Random r = new Random();
      for(int i = 0; i < t.loop; i++){
        synchronized(t){
          t.val = r.nextInt(100);
          System.out.println(i+": random = "+ t.val);
          t.notifyAll();
          try{
            t.wait();
          } catch(Exception ex){}
        }
      }
    }
  }
  
  static class T2 extends Thread{
    public Test t;
    public T2(Test t){
      this.t = t;
    }
    
    @Override public void run(){
      for(int i = 0; i < t.loop; i++){
        synchronized(t){
          if(i == 0 && !t.r){ // T2 chạy trước mà T1 chưa chạy, T2 sẽ chờ
            try{
              t.wait();
            } catch (Exception x){}
          }
          System.out.println(i+": result = " + (t.val*t.val));
          t.notifyAll();
          if(i==t.loop-1)break; // hết vòng lặp, ngắt luôn để không đến wait()
          try{
            t.wait();
          } catch (Exception x){}
        }
      }
    }
  }

  
  static class Test{
    public int val = 0;
    public final int loop;
    public boolean r = false; // đã chạy hay chưa
    public Test(int l){
      loop = l;
    }
  }
}

Có thể chưa tối ưu cho lắm, bạn tham khảo và thay đổi phù hợp với mục đích của bạn.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?