[英]Run Java Threads sequentially
您將如何依次執行三個線程? 例如。 線程1,線程2,線程3。 不可能將一個線程的引用傳遞給另一線程並從run()方法調用。
因此代碼應如下所示:
Thread1.start();
Thread2.start();
Thread3.start();
和輸出應該
Printing Thread1
Printing Thread2
Printing Thread3
這可以通過使用ThreadPoolExecutor並使用阻塞隊列來實現,但即使那樣也不是可以接受的答案。
您可以使用Executors.newSingleThreadExecutor() ,但嚴格來說,這僅啟動一個 Thread
,因此可能不是預期的解決方案。
僅使用Thread
類的最簡單的解決方案:
Thread1.start();
Thread1.join();
Thread2.start();
Thread2.join();
Thread3.start();
Thread3.join();
(為了清楚起見,我省略了異常處理, Thread.join()
可以拋出InterruptedException
)
最簡單的答案是
Thread1.run();
Thread2.run();
Thread3.run();
不切實際的問題所帶來的問題是,他們通常會得到一個信息不足的答案。 ;)
擁有線程的全部目的是同時運行它們。 如果您根本不這樣做,請不要使用線程。
你可能會這么說; 您不能調用run()方法,在這種情況下,您不能使用ThreadPoolExecutor,因為它會為您調用run()方法。 即多數民眾贊成提交()最終做什么。
編輯:結果是完全確定性的,因為涉及線程的事實是不可靠的。
static class PrintThread extends Thread {
public PrintThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++)
System.out.println(getName() + ": " + i);
}
}
public static void main(String args[]) {
Thread thread1 = new PrintThread("A");
Thread thread2 = new PrintThread("B");
Thread thread3 = new PrintThread("C");
thread1.run();
thread2.run();
thread3.run();
}
版畫
A: 0
A: 1
.. deleted ..
C: 98
C: 99
如預期的那樣。
在java.util.concurrent包中使用ExecutorService 。 更精確地使用Executors.newSingleThreadExecutor();
可以使用ExecutorService順序執行線程。 查找以下示例。
public class SeqThread {
public static void main(String[] arg) {
new SeqThread().execute();
}
public void execute() {
try {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(R);
executor.submit(R2);
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Runnable R = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++)
{
System.out.println("In Thread One "+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Runnable R2 = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++)
{
System.out.println("In Thread Two="+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
}
由於這是一個面試問題,因此他們正在尋找特定的知識,而不是“這樣做顯然更好”的答案。 看來他們很可能會逐個解決方案,直到獲得所需的答案。
他們想看看您是否可以自己實現線程間通信,這很奇怪。 但是他們不希望您以簡單的方式做到這一點(可用線程引用)。 否則,您可以只執行thread.join()
。
因此,讓所有三個線程都獲取一些共享內存(同步的靜態類)。 讓每個線程檢查一個public static int nextThread()
。 成功比較它們是下一個線程后,他們應該執行工作,並使用要處理的下一個線程的值更新public static setNextThread(int value)
。
關鍵是要以線程安全的方式執行此操作; 但是,如果可以保證唯一的線程標識符,並確保沒有兩個線程具有相同的標識符,則可以(經過仔細的編碼)甚至可以做到不同步。
如果與調用這些線程的各種方式無關 , 則從理論上講,他們應該使用獲取一個通用的sempahore ,並在完成打印后將其釋放。
JDK有一個內置的信號燈 。
強制線程以有序方式運行就像殺死了多線程這一概念,更像是單線程程序的子例程執行。 作為面試的問題,一切都很好。 這是不是用4個線程而是用50個線程測試邏輯的程序-
public class Outer {
private Thread[] jobs;
private String[] names;
private int indx;
public Outer(int numOfThreads) {
jobs = new Thread[numOfThreads];
names = new String[numOfThreads];
indx = numOfThreads - 1;
}
class Inner implements Runnable {
public void run() {
while (true) {
if (names[indx].equals(Thread.currentThread().getName())) {
indx--;
break;
}
else {
try { Thread.sleep(20); } catch(InterruptedException ie) {}
}
}
// now current thread will join behind the previous one..
if (indx >= 0) try { jobs[indx].join(); } catch(InterruptedException ie) {}
/***** YOUR ACTUAL CODE GOES FROM HERE *****/
// at last check is it working ?
System.out.println(Thread.currentThread().getName());
}
}
public void f() {
Inner target = new Inner();
// initializing all threads..
for (int i = 0; i < jobs.length; jobs[i++] = new Thread(target));
for (int i = 0; i < names.length; names[i] = jobs[i++].getName());
// checking name of threads..
for (int i = 0; i < names.length; System.out.println(names[i++]));
System.out.println();
// now we start all threads..
for (int i = 0; i < jobs.length; jobs[i++].start());
}
public static void main(String[] args) {
new Outer(50).f(); // testing logic not with 4 but 50 threads..
}
}
您可以在此處找到所有內容: http : //download.oracle.com/javase/tutorial/essential/concurrency/index.html
尤其要閱讀有關線程之間的通知和同步的信息。
附言:請記住,即使通過面試,您仍然必須工作! :)
(好吧,我會給出一些提示:看起來像Object.wait()
和Object.notifyAll()
這樣的方法的描述,這是最簡單但也非常有用的機制)
newSingleThreadExecutor。 單線程執行程序創建一個工作線程來處理任務,如果它意外死亡,則將其替換。 確保根據任務隊列強加的順序(FIFO,LIFO,優先級順序)順序處理任務。
我使用了基本的線程通信模型,它也可以更加簡化。 假設您有3個線程,其中一個正在打印0,第二個正在打印奇數,第三個正在打印偶數,例如01 02 03 04 05 ....
public class app{
int status=0;
public static void main(String[] args) throws InterruptedException{
app obj = new app();
Thread t1 = new Thread(new print(obj,0));
Thread t2 = new Thread(new print(obj,1));
Thread t3 = new Thread(new print(obj,2));
t1.start();t2.start();t3.start();
}
}
class print implements Runnable{
app obj;
int a;
public print(app obj, int a) {
this.obj=obj;
this.a=a;
}
@Override
public void run() {
try{
if(a==0){
synchronized(obj){
for (int i = 0; i < 21; i++) {
while(obj.status!=0 && obj.status!=3){
obj.wait();
}
System.out.print(0);
if(obj.status==0)//even sets status to 0 so next one is odd
obj.status=1;
else//odd sets status to 3 so next one is even
obj.status=2;
obj.notifyAll();
}
}
}
else if(a%2!=0){
synchronized (obj) {
for (int i = 0; i < 11; i++) {
while(obj.status!=1){
obj.wait();
}
System.out.print(a);
a+=2;
obj.status=3;
//3 decides 0 came after odd, so next one
//after zero is even
obj.notifyAll();
}
}
}
else{
synchronized (obj) {
for (int i = 0; i < 11; i++) {
while(obj.status!=2){
obj.wait();
}
System.out.print(a);
a+=2;
obj.status=0;
obj.notifyAll();
}
}
}
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
這可能是一個棘手的問題。 也許他們不想聽到針對此特定問題的解決方案,但希望您回溯到問題的根源並提出更好的解決方案。
我不確定我是否完全理解了這個問題,但是這似乎是我們想要按順序打印線程的情況。 一個示例是使用線程按如下順序打印值:
線程-0輸出:1
線程-1個輸出:2
線程-2輸出:3
線程-0輸出:4
線程-1輸出:5
線程-2輸出:6,依此類推。
如果這是必需的,則可以編寫n個線程的通用解決方案,其中每個線程將等待其輪換(使用將嘗試獲取鎖的公共對象)。
class ResourceLock {
private volatile int currentThreadId;
private final int totalThreads;
public ResourceLock(int threadsCount) {
this.currentThreadId = 0;
this.totalThreads = threadsCount;
}
public void assignTokenToNextThread(int currentThreadNum) {
this.currentThreadId = (currentThreadNum + 1) % totalThreads;
}
public int getCurrentThreadId() {
return currentThreadId;
}
}
現在,一個工作線程將完成其工作,並使用上述類的實例進行鎖定:
class Worker extends Thread {
private final ResourceLock resourceLock;
private final int threadId; // id of this thread
private final AtomicInteger counter; // counter shared by all threads, will print number in sequence.
private volatile boolean running = true; // flag to stop this thread when necessary
public Worker(ResourceLock resourceLock, int threadNumber, AtomicInteger counter) {
this.resourceLock = resourceLock;
this.threadId = threadNumber;
this.counter = counter;
}
@Override
public void run() {
while (running) {
try {
synchronized (resourceLock) {
while (resourceLock.getCurrentThreadId() != this.threadId) {
resourceLock.wait();
}
System.out.println("Thread:" + threadId + " value: " + counter.incrementAndGet());
Thread.sleep(1000);
resourceLock.assignTokenToNextThread(this.threadId);
resourceLock.notifyAll();
}
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
public void shutdown() {
running = false;
}
}
可以測試為:
public static void main(String[] args) throws InterruptedException {
final int threadsCount = 3;
final ResourceLock lock = new ResourceLock(threadsCount);
Worker[] threads = new Worker[threadsCount];
final AtomicInteger counter = new AtomicInteger(0);
for(int i=0; i<threadsCount; i++) {
threads[i] = new Worker(lock, i, counter);
threads[i].start();
}
Thread.sleep(20000);
System.out.println("Will try to shutdown now...");
for(Worker worker: threads) {
worker.shutdown();
}
}
public static void main(String[] args)throws InterruptedException {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r,"A");
Thread t2 = new Thread(r,"B");
Thread t3 = new Thread(r,"C");
t1.start();
Thread.sleep(1000);
t2.start();
Thread.sleep(1000);
t3.start();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.