[英]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.