[英]Java Multithreaded Program NotifyListener Behavior
我一直在編寫一個簡單的程序,試圖理解 Java 的多線程特性,並結合 Listeners 用作 Thread 關閉時的通知代理。 以下是正在使用的接口/類(主要從 web 中獲取並稍作調整):
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final NotifyingThread thread);
}
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners = new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
@Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
Class InvokeThread 版本 1
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InvokeThread implements ThreadCompleteListener{
List<String> synList = Collections.synchronizedList(new ArrayList<String>());
int threadNotifyCount = 0;
String threadList = "";
public static void main(String[] args) {
InvokeThread ma_0 = new InvokeThread();
ma_0.execute(args);
}
@Override
public void notifyOfThreadComplete(NotifyingThread thread) {
String _temp = threadList.substring(0, threadList.length()-1);
threadNotifyCount++;
if(threadNotifyCount == _temp.split(",").length) {
Collections.sort(synList);
System.out.println(thread.getName() + ": " + synList);
}
}
public String execute(String[] args) {
// Start the Thread
NotifyingThread thread1 = new NotifyingThread() {
@Override
public void doRun() {
synchronized (this) {
// synList.addAll(Arrays.asList("zebra", "cow", "rabbit"));
threadList = this.getName() + "," + threadList;
synList.addAll(Arrays.asList(args[0].split(",")));
}
}
};
thread1.addListener(this);
thread1.start();
NotifyingThread thread2 = new NotifyingThread() {
@Override
public void doRun() {
synchronized (this) {
threadList = this.getName() + "," + threadList;
synList.addAll(Arrays.asList(args[idx].split(",")));
}
}
};
thread2.addListener(this);
thread2.start();
return "";
}
}
Class InvokeThread 的版本 2
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InvokeThread implements ThreadCompleteListener{
List<String> synList = Collections.synchronizedList(new ArrayList<String>());
int threadNotifyCount = 0;
String threadList = "";
public static void main(String[] args) {
InvokeThread ma_0 = new InvokeThread();
ma_0.execute(args);
}
@Override
public void notifyOfThreadComplete(NotifyingThread thread) {
String _temp = threadList.substring(0, threadList.length()-1);
threadNotifyCount++;
if(threadNotifyCount == _temp.split(",").length) {
Collections.sort(synList);
System.out.println(thread.getName() + ": " + synList);
}
}
public String execute(String[] args) {
int argsCount = args.length;
for(int idx=0;idx<argsCount;idx++) {
NotifyingThread thread = new NotifyingThread() {
@Override
public void doRun() {
synchronized (this) {
threadList = this.getName() + "," + threadList;
synList.addAll(Arrays.asList(args[1].split(",")));
}
}
};
thread.addListener(this);
thread.start();
}
return "";
}
}
輸入 arguments:
"zebra,cow,rabbit"
"giraffe,camel,buffalo"
上面給出了給定 class InvokeThread 的兩個版本。 第一個版本確實打印了字符串對象的排序列表,始終如一。 第二個版本偶爾什么也不打印。 請幫助我了解發生的情況。 TIA。
編輯 - 1(在更改代碼以修復所羅門在評論部分報告的錯誤之后):
NotifyingThread 版本 2:
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners = new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
private int idx;
public NotifyingThread(int index) {
this.idx = index;
}
@Override
public final void run() {
try {
doRun(idx);
} finally {
notifyListeners();
}
}
public abstract void doRun(int idx);
}
InvokeThread 2.1 版:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InvokeThread implements ThreadCompleteListener{
List<String> synList = Collections.synchronizedList(new ArrayList<String>());
int threadNotifyCount = 0;
String threadList = "";
public static void main(String[] args) {
InvokeThread ma_0 = new InvokeThread();
ma_0.execute(args);
}
@Override
public void notifyOfThreadComplete(NotifyingThread thread) {
String _temp = threadList.substring(0, threadList.length()-1);
threadNotifyCount++;
if(threadNotifyCount == _temp.split(",").length) {
Collections.sort(synList);
System.out.println(thread.getName() + ": " + synList);
}
}
public String execute(String[] args) {
int argsCount = args.length;
for(int idx=0;idx<argsCount;idx++) {
NotifyingThread thread = new NotifyingThread(idx) {
@Override
public void doRun(int idx) {
synchronized (this) {
// synList.addAll(Arrays.asList("giraffe", "camel", "buffalo"));
threadList = this.getName() + "," + threadList;
synList.addAll(Arrays.asList(args[idx].split(",")));
}
}
};
thread.addListener(this);
thread.start();
}
return "";
}
}
該夾具確實修復了報告的原始問題,即此 class 的 v2 不偶爾打印列表。 但是,我想保留這個問題,以要求澄清所羅門關於不同步的評論。
以下更改(作為所羅門提示的結果)提供了夾具:
NotifyingThread 版本 2:
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners = new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
private int idx;
public NotifyingThread(int index) {
this.idx = index;
}
@Override
public final void run() {
try {
doRun(idx);
} finally {
notifyListeners();
}
}
public abstract void doRun(int idx);
}
InvokeThread 2.1 版:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InvokeThread implements ThreadCompleteListener{
List<String> synList = Collections.synchronizedList(new ArrayList<String>());
int threadNotifyCount = 0;
String threadList = "";
public static void main(String[] args) {
InvokeThread ma_0 = new InvokeThread();
ma_0.execute(args);
}
@Override
public void notifyOfThreadComplete(NotifyingThread thread) {
String _temp = threadList.substring(0, threadList.length()-1);
threadNotifyCount++;
if(threadNotifyCount == _temp.split(",").length) {
Collections.sort(synList);
System.out.println(thread.getName() + ": " + synList);
}
}
public String execute(String[] args) {
int argsCount = args.length;
for(int idx=0;idx<argsCount;idx++) {
NotifyingThread thread = new NotifyingThread(idx) {
@Override
public void doRun(int idx) {
synchronized (this) {
// synList.addAll(Arrays.asList("giraffe", "camel", "buffalo"));
threadList = this.getName() + "," + threadList;
synList.addAll(Arrays.asList(args[idx].split(",")));
}
}
};
thread.addListener(this);
thread.start();
}
return "";
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.