回答
線程也是可運行的。你可以簡單地依次運行它們:
t1.run();
t2.run();
t3.run();
這顯然沒什麼興趣。
假設他們想要的線程並行運行,一個解決辦法是讓每個線程開始下一個,因爲the JMM guarantees that:
調用開始()上線之前發生的任何行動在開始的線程中。
與創建它們的其他各胎面創建一個優先級隊列。 然後,您可以在完成後應用Thread.join
,從優先級隊列中刪除該線程,然後再次執行隊列的第一個元素。 僞代碼:
pthread [3] my_threads
my_queue
for t in pthreads:
my_queue.queue(t)
while !my_queue.empty()
pop the head of the queue
wait until it complets
thread.join()
實現留作練習,所以下次你得到它的權利!
在每個線程(除T1)的開始,使之加入到通話(),它的前身。使用執行程序(而不是直接線程)是另一種選擇。人們也可以看看使用信號量--T1應該在完成時釋放許可證,T2應該嘗試獲得兩個許可證,並且在完成時釋放它們,T3應該嘗試獲得三個許可證&等等。使用加入或執行者將是首選路線。
這將是最簡單,最笨的辦法:
final Thread t1 = new Thread(new T1()); // assume T1 is a Runnable
t1.start();
t1.join();
final Thread t2 = new Thread(new T2());
t2.start();
t2.join();
final Thread t3 = new Thread(new T3());
t3.start();
t3.join();
一種方式做到這一點會是像下面這樣。雖然這很複雜。您可能需要使用java.util.concurrent.CyclicBarrier
類。
當它完成每個線程設置布爾值,並通知下一個線程繼續。儘管這是一個AtomicBoolean
類,我們需要的所以我們可以wait()
和notify()
就可以了。
傳入鎖對象或者在T2
和T3
上可能有一個begin()
方法會更清晰,因此我們可以將這些鎖隱藏在這些對象內部。
final Object lock2 = new Object();
final Object lock3 = new Object();
boolean ready2;
boolean ready3;
...
public T1 implements Runnable {
public void run() {
...
synchronized (lock2) {
// notify the T2 class that it should start
ready2 = true;
lock2.notify();
}
}
}
...
public T2 implements Runnable {
public void run() {
// the while loop takes care of errant signals
synchronized (lock2) {
while (!ready2) {
lock2.wait();
}
}
...
// notify the T3 class that it should start
synchronized (lock3) {
ready3 = true;
lock3.notify();
}
}
}
...
public T3 implements Runnable {
public void run() {
// the while loop takes care of errant signals
synchronized (lock3) {
while (!ready3) {
lock3.wait();
}
}
...
}
}
最明顯的,也是最簡單的方法已經發表@Assylias - 有T1 run方法創建/啓動T2和T2運行方法創建/啓動T3。
是,恕我直言,近乎毫無意義,但它可以做。
解決方案使用JOIN()不回答這個問題 - 他們保證線程的終止是有序的,他們不運行。如果面試官不明白,那麼無論如何你都需要找到另一份工作。
在接受採訪時,我的回答是'For *爲什麼?線程通常用於避免你正在問的問題!'。
猜測面試官問的是三個線程按順序進行工作。例如,如果一個線程打印1,4,5 ...第2,5,8和三分之三3,6,9 etc ..輸出應該be 1,2,3,4,5 ..... Ist thread print 1 and give 2nd thread to print 2..etc。,
我試過使用cyclebarriers。只要'one'打印1IT給人機會,兩成調用cb.wait,當兩個運行它會依次調用三個類似的方式,它會continue.Let我知道,如果THR在代碼中的任何錯誤
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class one implements Runnable{
CyclicBarrier cb;
one(CyclicBarrier cb){this.cb=cb;}
public void run(){
int i=1;
while(true)
{
System.out.println(i);
try {
Thread.sleep(1000);
cb.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i=i+3;
}
}
}
class two implements Runnable{
CyclicBarrier cb;
int i=2;
two(CyclicBarrier cb){this.cb=cb;}
public void run(){
System.out.println(i);
try {
cb.await();
i=i+3;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class oneTwoThree {
public static void main(String args[]){
Runnable threePrinter = new Runnable() {
int i=3;
public void run() {
System.out.println(i);
i=i+3;
}
};
CyclicBarrier bar2 =new CyclicBarrier(1,threePrinter);//, barrier1Action);
two twoPrinter =new two(bar2);
CyclicBarrier bar1 =new CyclicBarrier(1,twoPrinter);
Thread onePrinter=new Thread(new one(bar1));
onePrinter.start();
}
}
今天在接受採訪時,我問到了完全相同的問題。無法回答。我正在尋找這個問題的答案,最終落在你的回答裏。它工作完美。 – siddhartha 2017-12-16 17:20:28
使用在啓動t之前,thread isAlive方法他線程T2和T3。
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
Thread t3 = new Thread(new T3());
t1.start();
if(t1.isAlive()){
t2.start();
}
if(t2.isAlive()){
t3.start();
}
我在一個更簡單的方法..嘗試使用等待和通知。(在我的上一個職位相對於循環障礙的方法)。
它使用'狀態'類......它有三種狀態:1,2,3。(默認值3)。 當它在3時,它觸發t1,在1將觸發t2,在2將觸發t3,等等。
類: 狀態// INT I = 3 T1 //輸出1,4,7 ...... T2 //打印2,5,8 T3 //打印3,6,9等,
請讓我知道您的意見或代碼中是否有任何問題。謝謝。
下面是代碼:
public class State {
private int state ;
public State() {
this.state =3;
}
public synchronized int getState() {
return state;
}
public synchronized void setState(int state) {
this.state = state;
}
}
public class T1 implements Runnable {
State s;
public T1(State s) {
this.s =s;
}
@Override
public void run() {
int i =1;
while(i<50)
{
//System.out.println("s in t1 "+ s.getState());
while(s.getState() != 3)
{
synchronized(s)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
//if(s.getState() ==3)
if(s.getState()==3)
System.out.println("t1 "+i);
s.setState(1);
i = i +3 ;
s.notifyAll();
}
}
}
}
public class T2 implements Runnable {
State s;
public T2(State s) {
this.s =s;
}
@Override
public synchronized void run() {
int i =2;
while(i<50)
{
while(s.getState() != 1)
{
synchronized(s)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
//if(s.getState() ==3)
if(s.getState()==1)
System.out.println("t2 "+i);
s.setState(2);
i = i +3 ;
s.notifyAll();
}
}
}
}
public class T3 implements Runnable {
State s;
public T3(State s) {
this.s =s;
}
@Override
public synchronized void run() {
int i =3;
while(i<50)
{
while(s.getState() != 2)
{
synchronized(s)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
if(s.getState()==2)
System.out.println("t3 "+i);
i = i +3 ;
s.setState(3);
s.notifyAll();
}
}
}}
public class T1t2t3 {
public static void main(String[] args) {
State s = new State();
Thread t1 = new Thread(new T1(s));
Thread t2 = new Thread(new T2(s));
Thread t3 = new Thread(new T3(s));
t1.start();
t2.start();
t3.start();
}
}
同時使用,你可以運行N的這種方式線程數試試下面的代碼。
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicExecutionOfThreads {
public static void main(String args[]) {
int totalNumOfThreads = 10;
PrintJob printJob = new PrintJob(totalNumOfThreads);
/*
MyRunnable runnable = new MyRunnable(printJob, 1);
Thread t1 = new Thread(runnable);
MyRunnable runnable2 = new MyRunnable(printJob, 2);
Thread t2 = new Thread(runnable2);
MyRunnable runnable3 = new MyRunnable(printJob, 3);
Thread t3 = new Thread(runnable3);
t1.start();
t2.start();
t3.start();
*/
//OR
ExecutorService executorService = Executors
.newFixedThreadPool(totalNumOfThreads);
Set<Runnable> runnables = new HashSet<Runnable>();
for (int i = 1; i <= totalNumOfThreads; i++) {
MyRunnable command = new MyRunnable(printJob, i);
runnables.add(command);
executorService.execute(command);
}
executorService.shutdown();
}
}
class MyRunnable implements Runnable {
PrintJob printJob;
int threadNum;
public MyRunnable(PrintJob job, int threadNum) {
this.printJob = job;
this.threadNum = threadNum;
}
@Override
public void run() {
while (true) {
synchronized (printJob) {
if (threadNum == printJob.counter) {
printJob.printStuff();
if (printJob.counter != printJob.totalNumOfThreads) {
printJob.counter++;
} else {
System.out.println();
// reset the counter
printJob.resetCounter();
}
printJob.notifyAll();
} else {
try {
printJob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class PrintJob {
int counter = 1;
int totalNumOfThreads;
PrintJob(int totalNumOfThreads) {
this.totalNumOfThreads = totalNumOfThreads;
}
public void printStuff() {
System.out.println("Thread " + Thread.currentThread().getName()
+ " is printing");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void resetCounter() {
this.counter = 1;
}
}
package thread;
class SyncPrinter {
public static void main(String[] args) {
SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);
printAction1.setDependentAction(printAction4);
printAction2.setDependentAction(printAction1);
printAction3.setDependentAction(printAction2);
printAction4.setDependentAction(printAction3);
new Thread(printAction1, "T1").start();;
new Thread(printAction2, "T2").start();
new Thread(printAction3, "T3").start();
new Thread(printAction4, "T4").start();
}
}
class SyncPrinterAction implements Runnable {
private volatile boolean dependent;
private SyncPrinterAction dependentAction;
int[] data;
public void setDependentAction(SyncPrinterAction dependentAction){
this.dependentAction = dependentAction;
}
public SyncPrinterAction(int[] data, boolean dependent) {
this.data = data;
this.dependent = dependent;
}
public SyncPrinterAction(int[] data, SyncPrinterAction dependentAction, boolean dependent) {
this.dependentAction = dependentAction;
this.data = data;
this.dependent = dependent;
}
@Override
public void run() {
synchronized (this) {
for (int value : data) {
try {
while(dependentAction.isDependent())
//System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dependentAction.setDependent(true);
System.out.println(Thread.currentThread().getName() + " :: " +value);
dependent = false;
}
}
}
private void setDependent(boolean dependent) {
this.dependent = dependent;
}
private boolean isDependent() {
return dependent;
}
}
併發封裝具有更好的類使用共享對象。 其中一種方式就是這樣。
public static void main(String[] args) {
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
ThreadId threadId = new RunInSequence.ThreadId();
threadId.setId(1);
Thread t1 = setThread("thread1",lock, condition, 1, 2, threadId);
Thread t2 = setThread("thread2",lock, condition, 2, 3, threadId);
Thread t3 = setThread("thread3",lock, condition, 3, 1, threadId);
t1.start();
t2.start();
t3.start();
}
private static class ThreadId {
private int id;
public ThreadId() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
private static Thread setThread(final String name,final Lock lock, final Condition condition, int actualThreadId, int nextThreadId,
ThreadId threadId) {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
lock.lock();
try {
while (threadId.getId() != actualThreadId) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+"prints: " + actualThreadId);
threadId.setId(nextThreadId);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
};
return thread;
}
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class Worker implements Runnable {
BlockingQueue<Integer> q = new LinkedBlockingQueue<>();
Worker next = null; // next worker in the chain
public void setNext(Worker t) {
this.next = t;
}
public void accept(int i) {
q.add(i);
}
@Override
public void run() {
while (true) {
int i;
try {
i = q.take(); // this blocks the queue to fill-up
System.out.println(Thread.currentThread().getName() + i);
if (next != null) {
next.accept(i + 1); // Pass the next number to the next worker
}
Thread.sleep(500); // Just sleep to notice the printing.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PrintNumbersSequentially {
public static void main(String[] as) {
Worker w1 = new Worker();
Worker w2 = new Worker();
Worker w3 = new Worker();
w1.setNext(w2);
w2.setNext(w3);
w3.setNext(w1);
new Thread(w1, "Thread-1: ").start();
new Thread(w2, "Thread-2: ").start();
new Thread(w3, "Thread-3: ").start();
//Till here all the threads have started, but no action takes place as the queue is not filled for any worker. So Just filling up one worker.
w1.accept(100);
}
}
我認爲這可以幫助你。
通過使用連接可以確保一個接一個地運行一個線程。
class MyTestThread implements Runnable{
public void run() {
System.out.println("==MyTestThread : START : "+Thread.currentThread().getName());
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " :i = "+i);
}
System.out.println("==MyTestThread : END : "+Thread.currentThread().getName());
}
}
public class ThreadJoinTest {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new MyTestThread(), "t1");
Thread thread2 = new Thread(new MyTestThread(), "t2");
thread1.start();
thread1.join();
thread2.start();
thread2.join();
System.out.println("====All threads execution===completed");
}
}
請格式化代碼並添加一些解釋。 – Sid 2017-02-10 06:17:46
我們如何能夠確保T2後,T1和T3線運行後該線程T2運行?
NOTE: Assuming that it is not about scheduling the threads in the required order
我們可以使用Condition接口。
我們需要綁定到單個Lock兩個條件:條件1協調T1和T2,條件2協調T2和T3。
通過條件1到T1和T2,條件2到T2和T3。
因此,我們必須對T2 條件1在它的run方法,這將是由T1信號等待(從T1的run方法,T1開始後/完成其任務)。
同樣具有T3 等待上條件2在它的運行方法,該方法將是通過T2信號通知(從T2的運行方法中,在啓動後/完成它的任務)。
有線程T1,T2和T3,我們如何確保線程T2在T1之後運行 並且線程T3在T2之後運行? 或 有三個線程T1,T2和T3?你如何確保Java中的序列T1,T2,T3? 問題主要是T3應該先完成,T2秒和T1完成。 我們可以使用使用線程類的join()方法。 爲確保執行三個線程,您需要先開始最後一個線程,例如T3,然後以相反的順序調用加入方法,例如T3調用T2.join, 和T2調用T1.join。這樣,T1將首先完成,T3將最後完成。
public class Test1 {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("start 1");
System.out.println("end 1");
}//run
});
final Thread t2 = new Thread(new Runnable() {
public void run() {
System.out.println(" start 2 ");
try {
t1.join(2000);
} catch (Exception e) {
e.getStackTrace();
}
System.out.println(" end 2");
}
}) ;
final Thread t3 = new Thread(new Runnable() {
public void run() {
System.out.println(" start 3 ");
try {
t2.join(4000);
}catch(Exception e) {
e.getStackTrace();
}
System.out.println(" end 3 ");
}
});
// we are reversing the order of the start() method
t3.start();
t2.start();
t1.start();
}
}
從輸出結果可以看出,線程開始順序不同,因爲您不知道哪個線程將獲得CPU。它是Thread Scheduler的決定,所以我們什麼都做不了。但是,您可以看到線程以正確的順序完成,即T1然後T2然後T3。
還有另一種方法。僞代碼是:
t1.start();
t1.join(); // signals t2 to wait
if(!t1.isAlive()) {
t2.start();// if t1 is finished then t2 will start
}
t2.join();//signals t3 to wait
if (!t2.isAlive()) {
t3.start();
}
讓我們完整的程序:
public class Tic implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("tic");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class Tac implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("tac");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class Toe implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("toe");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class RunThreads1 {
public static void main(String[] args) {
try {
Tic tic = new Tic();
Tac tac = new Tac();
Toe toe = new Toe();
Thread t1 = new Thread(tic);
Thread t2 = new Thread(tac);
Thread t3 = new Thread(toe);
t1.start();
t1.join(); // signals t2 to wait
if(!t1.isAlive()) {
t2.start();// if t1 is finished then t2 will start
}
t2.join();//signals t3 to wait
if (!t2.isAlive()) {
t3.start();
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
輸出是: 抽動 抽動 TAC TAC 腳趾 腳趾
- 1. 如何在完成另一個線程後運行一個線程
- 2. 從另一個線程運行線程
- 3. 如何確保線程在另一個CORE中執行?
- 4. 如何確保一個線程在其主線程完成後執行?
- 5. 在另一個線程中運行MBProgressHUD?
- 6. 如何在另一個線程中運行一個函數
- 7. 如何確定從另一個線程創建哪個線程?
- 8. 一個線程如何在另一個線程中被殺死
- 9. 從另一個線程運行幾個線程
- 10. 如何阻止UI線程從另一個線程或強制一個窗體在UI線程內運行
- 11. JMeter:如何在第一個線程完成後運行兩個線程
- 12. 如何運行另一個線程後一個線程已經完成了它的行動
- 13. 如何確保只有單個進程在線程中運行
- 14. 如何從另一個線程停止正在運行的線程?
- 15. 如何確保一個腳本只能在另一個腳本之後運行
- 16. 如何銷燬一個線程,暫停/掛起一個線程,恢復/運行一個線程?
- 17. 在另一個線程
- 18. 從另一個線程操作線程
- 19. 如何能在另一個線程
- 20. 如何將一個int值從一個線程發送到另一個線程?
- 21. 如何更新另一個線程中運行的另一個線程的用戶界面
- 22. 如何讓1個UI線程等待另一個UI線程
- 23. 訪問控制從另一個線程
- 24. 從另一個線程訪問BindingSource
- 25. 從另一個線程訪問ListBox.SelectedItems
- 26. 如何殺死線程從另一個線程在vala
- 27. 如何在另一個線程內啓動線程
- 28. 如何確保同步時,一個線程不斷髮送數據到另一個線程?
- 29. 一個線程在iPhone應用程序中殺死另一個線程(兩個線程都是主線程)?
- 30. Python:在一個線程中停止另一個線程從另一個線程結束
答:退出試圖使用分開的線程來完成明顯的順序任務。線程的要點是能夠在概念上一次完成兩件事情。如果一個線程必須在另一個線程開始之前完成,那麼他們沒有業務是獨立的線程;使他們這樣,然後試圖強制他們的序列只會增加你的複雜性。 – cHao 2012-07-18 17:55:01