3

我试图交错两个独立线程的执行。这样两者都有一个带有 10 次迭代的 run 方法,并且在每次迭代之后我想上下文切换线程。

线程 A 启动,在执行打印之类的操作后,将控制权传递给线程 B。然后线程 B 打印并将控制权传回给 A,依此类推,直到两者都完成。

这样做的有效机制是什么?

我附上了一个示例代码。希望你能帮忙。

// Suspending and resuming a thread for Java 2

class NewThread implements Runnable {
  String name; // name of thread
  Thread t;
 // boolean suspendFlag;

  NewThread(String threadname) {
    name = threadname;
    t = new Thread(this, name);
    System.out.println("New thread: " + t);
  //  suspendFlag = false;
    t.start(); // Start the thread
  }
  public String getState()
  {
    Thread t=Thread.currentThread();

    return t.getState().toString(); 
  }
  // This is the entry point for thread.
  public void run() {
    try {
      for(int i = 15; i > 0; i--) {
        System.out.println(name + ": " + i);
        Thread.sleep(200);
        synchronized(this) {
            //SuspendResume.suspendFlag2=false;
            SuspendResume.suspendFlag1=true;
          while(SuspendResume.suspendFlag1) {
            wait();
            //System.out.println(SuspendResume.ob1.t.getState().toString());
           // if(SuspendResume.ob2.t.getState().toString()=="WAITING")
            //  SuspendResume.ob2.t.notify();
          }
        }
      }
    } catch (InterruptedException e) {
      System.out.println(name + " interrupted.");
    }
    System.out.println(name + " exiting.");
  }

  void mysuspend() {
 //   suspendFlag = true;
  }

  synchronized void myresume() {
   // suspendFlag = false;
    notify();
  }
}
class NewThread2 implements Runnable {
      String name; // name of thread
      Thread t;
     // boolean suspendFlag;

      NewThread2(String threadname) {
        name = threadname;
        t = new Thread(this, name);
        System.out.println("New thread: " + t);
      //  suspendFlag = false;
        t.start(); // Start the thread
      }
      public String getState()
      {
        Thread t=Thread.currentThread();

        return t.getState().toString(); 
      }
      // This is the entry point for thread.
      public void run() {
        try {
          for(int i = 15; i > 0; i--) {
            System.out.println(name + ": " + i);
            Thread.sleep(1000);
            synchronized(this) {
                //SuspendResume.suspendFlag1=false;
                //while(SuspendResume.suspendFlag1) {
         //     while(suspendFlag) {
                //wait();
                //System.out.println(SuspendResume.ob2.t.getState().toString());
                //if(SuspendResume.ob1.t.getState().toString()=="WAITING")
                //SuspendResume.ob1.t.notify();
              //}
                SuspendResume.suspendFlag1=false;
                notify();
            }
          }
        } catch (InterruptedException e) {
          System.out.println(name + " interrupted.");
        }
        System.out.println(name + " exiting.");
      }

      void mysuspend() {
     //   suspendFlag = true;
      }

      synchronized void myresume() {
       // suspendFlag = false;
        notify();
      }
    }
class SuspendResume {
     static boolean suspendFlag1=false;
    static NewThread ob1 = new NewThread("One");
    static NewThread2 ob2 = new NewThread2("Two");

   // static boolean suspendFlag2=false;

  public static void main(String args[]) {


    try {
      //Thread.sleep(1000);
      //ob1.mysuspend();
      //System.out.println("Suspending thread One");
      //Thread.sleep(1000);
      //ob1.myresume();
      //System.out.println("Resuming thread One");
     // ob2.mysuspend();
      //System.out.println("Suspending thread Two");
      Thread.sleep(1000);
     // ob2.myresume();
      //System.out.println("Resuming thread Two");
    } catch (InterruptedException e) {
      System.out.println("Main thread Interrupted");
    }

    // wait for threads to finish
    try {
      System.out.println("Waiting for threads to finish.");
      System.out.println(ob1.getState());
      System.out.println(ob1.getState());
      ob1.t.join();
      ob2.t.join();
    } catch (InterruptedException e) {
      System.out.println("Main thread Interrupted");
    }

    System.out.println("Main thread exiting.");
  }
}
4

4 回答 4

2

首先,我不确定你有什么样的场景,你想一遍又一遍地顺序运行两个线程。这听起来像是一个线程在一个循环中运行两种不同的方法。尽管如此,这听起来像是一个有趣的挑战,所以我接受了。

利用 Java 5 的Exchanger类,解决方案变得非常小。我最终得到了一个Runnable类。我使用它们的两个实例将布尔值 true 和布尔值 false 相互传递。Exchanger 类有助于以线程安全的方式传递布尔值。Runnable 仅在其具有布尔真值时“执行”其代码。

package interleavedexample;

import java.util.concurrent.Exchanger;
import java.util.logging.Logger;

/**
 *
 */
public class InterleavedRunnable implements Runnable {

  private final String name;

  private final Exchanger<Boolean> exchanger;

  private Boolean state;

  public InterleavedRunnable(String name, Exchanger<Boolean> exchanger, 
       Boolean state) {
    this.name = name;
    this.exchanger = exchanger;
    this.state = state;
  }         

  @Override
  public void run() {
    try {
      while (true) {
        if (state) {
          Logger.getLogger(getClass().getName()).info(name + " is running");
        }
        state = exchanger.exchange(state);
      }
    } catch (InterruptedException ex) {
      Logger.getLogger(name).info("Interrupted");
    }
  }

设置 runnables 非常简单:

  public static void main(String[] args) {
    Exchanger<Boolean> exchanger = new Exchanger<Boolean>();
    Thread thread1 = new Thread(new InterleavedRunnable("Thread 1", exchanger, true));
    Thread thread2 = new Thread(new InterleavedRunnable("Thread 2", exchanger, false));
    thread1.start();
    thread2.start();
  }

只要您可以在 Java API(或知名库)中找到现有功能,您就应该充分利用它们。您编写的代码行数越少,需要维护的行数就越少。

于 2013-03-11T13:14:52.780 回答
1

为此使用等待和通知。

public class Thread1 implements Runnable {

@Override
public void run() {
    while(true){
        synchronized (Main.obj) {
            try {
                Main.obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


        System.out.println("1");



        synchronized (Main.obj) {

            Main.obj.notify();

        }
    }

}

}


public class Thread2 implements Runnable{

@Override
public void run() {
    while(true){
        synchronized (Main.obj) {
            try {
                Main.obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("2");
        synchronized (Main.obj) {

            Main.obj.notify();

        }
    }

}
}


public class Main {

public volatile static Object obj =  new Object();

/**
 * @param args
 */
public static void main(String[] args) {

    Thread t1 = new Thread(new Thread1());
    Thread t2 = new Thread(new Thread2());
    t1.start();
    t2.start();
    synchronized (obj) {
        obj.notifyAll();
    }

}

}
于 2013-03-11T13:25:08.540 回答
1

The 'OS Sycnro 101' solution is to use two semaphores, one for each thread, and swap over one 'GO' token/unit between them. Start both threads and then give the token to whichever thread you want to go first.

于 2013-03-11T12:51:19.463 回答
1

没有正确回答您的问题。如果你只想在线程A执行结束后才执行线程B,那么多线程根本没有意义。您可以简单地将线程 B 的内容放入线程 A 的 run() 方法中。

如果非常需要,那么您可以尝试在两个对象上使用 wait() 和 notify() 方法。像这样的东西。

Class ClassA implements runnable{
    Message messageA;
    Message messageB;
    public ClassA(Message messageA,,Message messageB){
        this.messageA = messageA;
        this.messageB = messageB;
    }
    public void run(){
        for(;loop contition;){
            //code here
            messageB.notify();
            messageA.wait();
        }
    }
}
Class ClassB implements runnable{
    Message messageA;
    Message messageB;
    public ClassB(Message messageA,Message messageB){
        this.messageA = messageA;
        this.messageB = messageB;
    }
    public void run(){
        for(;loop condition;){
            messageB.wait();
            //code here
            messageA.notify();
        }
    }
}
  • 现在在主 messageA 和 messageB 中创建两个对象,并将它们都传递到每个线程的构造函数中。
于 2013-03-11T13:39:47.397 回答