Rur*_*ano 3 java multithreading
我很抱歉这太长了,而且可能看起来太多了,但如果你能一目了然地弄清楚什么是错的,请告诉我.
在这个程序中,我尝试在每次获取一个令牌时从键盘输入一些单词(短语)并将其分配给一个对象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();
}
}
Run Code Online (Sandbox Code Playgroud)
package Multithreads;
public interface Storer {
public void set(String token);
public String get();
}
Run Code Online (Sandbox Code Playgroud)
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");
}
}
Run Code Online (Sandbox Code Playgroud)
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");
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
导致应用程序永远运行的问题是这是一个无限循环:
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
Run Code Online (Sandbox Code Playgroud)
因为你没有减少i.你试图用来突破循环的中断机制(通过例外!)也被打破了.
这Thread.sleep(15*rd.nextInt(2000))条线看起来像一个黑客,这样你就可以InterruptedException在任务被中断时获得,但是:
Thread.interrupted().此外,办法,因为有一个机会,中断将发生不可靠反正以后在你正在等待/测试的地步; 即在get()通话中.如果该get()调用永远不会返回,因为它store是空的并且检索器已经结束......那么你将"永远"等待.
最后一个问题.app.shutdownNow()如果您希望执行程序服务中断工作线程,则需要调用...
如果我试图实现这个(使用中断),我会改变它,get并且set不会"吞噬"中断.如果他们看到中断,他们应该:
InterruptedException传播(在相关清理后),或| 归档时间: |
|
| 查看次数: |
325 次 |
| 最近记录: |