我很抱歉,這太長了,看起來太多問了,但如果你能弄清楚什麼是錯誤的一目瞭然,請讓我知道。我不知道這個線程有什麼問題,我想了解多線程
在這個程序中,我嘗試從鍵盤輸入一些單詞(短語),每次取一個令牌並將其分配給一個對象sharedStorer
(然後打印指定的值以跟蹤輸入內容,因爲我有一個鏈單詞分開輸入)。這是由一個線程(Retriever
類的主題,其implements
Runnable
)
還有就是class TokenReader
另一個線程讀取的sharedStorer
值,並打印出來完成。 TokenReader
等待輸入Retriever
,當Retriever
試圖輸入,而TokenReader
尚未讀取前一個標記Retriever
等待。
我的問題是最後TokenReader
等待永久Retriever
已完成其任務,因此程序永遠不會終止。
這裏是我用來執行所需任務的所有4個類(和1個接口)。
package Multithreads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExerciseTest {
public static void main(String[] args) {
ExecutorService app=Executors.newFixedThreadPool(2);
Storer st=new SyncStorer();
System.out.println("Operation performed\t\t Value");
try{
app.execute(new Retriever(st));
app.execute(new TokenReader(st));
}catch(Exception e){
e.printStackTrace();
}
app.shutdown();
}
}
package Multithreads;
public interface Storer {
public void set(String token);
public String get();
}
package Multithreads;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Retriever implements Runnable {
private Scanner scanner;
private String token;
private String currentToken;
private Storer sharedStorer;
private Random rd=new Random();
public int tokenLength=0;
public Retriever(Storer st) {
sharedStorer=st;
}
public Retriever() {
}
@Override
public void run() {
System.out.println("Enter a phrase");
scanner = new Scanner(System.in);
token=scanner.nextLine();
StringTokenizer tokenizer=new StringTokenizer(token);
while(tokenizer.hasMoreTokens())
{
tokenLength++;
currentToken=tokenizer.nextToken();
try{
Thread.sleep(10*rd.nextInt(2000));
sharedStorer.set(currentToken);
}catch(NoSuchElementException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Done Inputting The phrase");
}
}
package Multithreads;
import java.util.Random;
public class TokenReader implements Runnable {
private Random rd=new Random();
private Storer sharedStorer;
Retriever rtr=new Retriever();
private int count=rtr.tokenLength;
public TokenReader(Storer st) {
sharedStorer=st;
}
@Override
public void run() {
String str="null";
int i=0;
try {
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer done reading");
}
}
package Multithreads;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncStorer implements Storer {
private Lock accessLock=new ReentrantLock();
private Condition canInput = accessLock.newCondition();
private Condition canRead = accessLock.newCondition();
private String string="null";
private boolean isEmpty=false;
@Override
public void set(String token) {
accessLock.lock();
try
{
while(isEmpty){
System.out.println("Retriever waiting");
canInput.await();
}
string=token;
isEmpty=true;
System.out.println("Retriever inputs\t\t "+string);
canRead.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
accessLock.unlock();
}
}
@Override
public String get() {
accessLock.lock();
try{
while(!isEmpty)
{
System.out.println("No token to read");
canRead.await();
}
isEmpty=false;
System.out.println("TokenReader reads\t\t "+string);
canInput.signal();
}catch(InterruptedException e)
{
e.printStackTrace();
}finally{
accessLock.unlock();
}
return string;
}
}
對於遲到,我改變並增加了i,因爲您注意到會導致無限循環,後來使用了使用ArrayblockingQueue的Consumer/Producer的方法,因爲我後來在我正在使用的書中找到它,它真的縮小了SyncStorer類中的線條,但問題不在那裏,因爲我後來才意識到它。關於如何讓線程在隨機數毫秒內進入休眠狀態,有助於忽略線程正在執行的時間。 nwy我無法理解你的答案,作爲一個初學者,我不想被困在先進的東西,我打算以後再回來。謝謝 –