2013-03-11 28 views
2

我想交錯執行兩個獨立的線程。因此兩者都有10次迭代的運行方法,並且在每次迭代之後,我想要上下文切換線程。java線程交錯

線程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."); 
    } 
} 
+0

首先,您可能在發佈之前清理了您的代碼。您可以使用'Thread.yield()'方法。它放棄CPU。但它不掛起調用線程,它處於就緒隊列中。 – 2013-03-11 12:48:25

+1

你爲什麼要這樣做?大多數情況下,線程完成一個工作單元然後退出。控制線程可以啓動線程並等待它們完成。 – 2013-03-11 12:49:01

+0

@GilbertLeBlanc大多數情況下,線程被寫爲while循環,直到應用關閉時纔會終止。 – 2013-03-11 12:54:16

回答

1

在「OS Sycnro 101」的解決方案是使用兩個信號量,一個用於每個線程,並交換對它們之間的一個「GO」令牌/單元。啓動兩個線程,然後將令牌傳遞給您想要首先轉到的線程。

1

首先,我不確定你有什麼樣的場景,你想要一次又一次地運行兩個線程。這聽起來像一個循環中運行兩種不同方法的單線程。無論如何,這聽起來像是一個有趣的挑戰,所以我拿起了它。

使用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"); 
    } 
    } 

設置的可運行是相當簡單:

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中的現有功能(或衆所周知的庫),你應該將其利用到最大限度。您編寫的代碼行越少,需要維護的行數越少。

+0

這是非常整潔,你認爲它會適用於我提到的情況。「我真正想要做的是給定一些線程並給出一個執行序列,例如A,B,C,A,B,C或者可能是C,B,B,A,C,A我希望我的線程按照提供的順序執行,每當線程產生時,它應該順序切換到下一個線程。 – user2156801 2013-03-15 10:50:23

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

} 

} 
1

沒有正確地得到您的問題。如果你想在線程A執行結束後才執行線程B,那麼根本沒有多線程的意義。您可以簡單地將線程B的內容放入線程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兩個對象,並在每個線程的構造函數傳遞他們兩個。