我写了一些多线程的爱好程序,在我的之前的工程/物理学习中也写了一些,因此我认为自己在同步/线程安全和原语方面具有初级以上的知识,这是普通用户在JMM和多个线程等方面感到挑战的地方。
我发现我需要的是没有适当方法将类的实例或静态成员标记为不同线程共享。想想看,我们有访问规则,如private/protected/public和命名getter/setter的约定以及很多其他事情。
但是线程呢?如果我想将变量标记为线程共享并遵循某些规则怎么办?Volatile/Atomic refs可能会完成任务,但有时您确实需要使用互斥锁。当您手动记住要使用某些内容时...您会忘记它:) - 在某个时候。
所以我有一个想法,我看到我不是第一个,我还检查了http://checkthread.org/example-threadsafe.html - 他们似乎有一个相当不错的代码分析器,我以后可能会尝试一下,这有点让我做一些我想做的事情。
这是什么意思? 好的,这让我有了帮助(是的,你可以泄露并破坏它,但不太可能),我可以将变量集(而不仅仅是变量)标记为线程共享,并且一旦完成,可以在编译时保证(我不能忘记同步某些方法)。 它还允许我在编译时标准化和执行测试,以查找可能的死锁(尽管目前我只在运行时实现了它,因为使用上述框架在编译时进行可能需要的不仅仅是java编译器)。
基本上,这对我非常有用,我想知道我是否正在重新发明轮子,或者这可能是我不知道的某种反模式。 我真的不知道该问谁。(哦,是的,Shared .run (SharedRunnable r,INPUT input) 就像...
我发现我需要的是没有适当方法将类的实例或静态成员标记为不同线程共享。想想看,我们有访问规则,如private/protected/public和命名getter/setter的约定以及很多其他事情。
但是线程呢?如果我想将变量标记为线程共享并遵循某些规则怎么办?Volatile/Atomic refs可能会完成任务,但有时您确实需要使用互斥锁。当您手动记住要使用某些内容时...您会忘记它:) - 在某个时候。
所以我有一个想法,我看到我不是第一个,我还检查了http://checkthread.org/example-threadsafe.html - 他们似乎有一个相当不错的代码分析器,我以后可能会尝试一下,这有点让我做一些我想做的事情。
但回到最初的问题。假设我们需要比消息传递框架更低级的东西,同时又需要比原始互斥锁更高级的东西...那我们有什么选择呢...嗯...没有?
所以基本上,我创造了一种纯Java超级简单的线程框架,它允许您将类成员声明为共享或非共享...嗯,有点像 :).
以下是如何使用它的示例:
public class SimClient extends AbstractLooper {
private static final int DEFAULT_HEARTBEAT_TIMEOUT_MILLIS = 2000;
// Accessed by single threads only
private final SocketAddress socketAddress;
private final Parser parser;
private final Callback cb;
private final Heart heart;
private boolean lookingForFirstMsg = true;
private BufferedInputStream is;
// May be accessed by several threads (T*)
private final Shared<AllThreadsVars> shared = new Shared<>(new AllThreadsVars());
.
.
.
.
static class AllThreadsVars {
public boolean connected = false;
public Socket socket = new Socket();
public BufferedOutputStream os = null;
public long lastMessageAt = 0;
}
要访问标记为线程共享的变量,您必须向Shared对象发送类似于可运行函数的函数对象:
public final void transmit(final byte[] data) {
shared.run(new SharedRunnable<AllThreadsVars, Object, Object>() {
@Override
public Object run(final AllThreadsVars sharedVariable, final Object input) {
try {
if (sharedVariable.socket.isConnected() && sharedVariable.os != null) {
sharedVariable.os.write(data);
sharedVariable.os.flush();
}
} catch (final Exception e) { // Disconnected
setLastMessageAt(0);
}
return null;
}
}, null);
}
当定义一个共享的可运行对象时,如下:
public interface SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> {
OUTPUT run(final SHARED_TYPE s, final INPUT input);
}
这是什么意思? 好的,这让我有了帮助(是的,你可以泄露并破坏它,但不太可能),我可以将变量集(而不仅仅是变量)标记为线程共享,并且一旦完成,可以在编译时保证(我不能忘记同步某些方法)。 它还允许我在编译时标准化和执行测试,以查找可能的死锁(尽管目前我只在运行时实现了它,因为使用上述框架在编译时进行可能需要的不仅仅是java编译器)。
基本上,这对我非常有用,我想知道我是否正在重新发明轮子,或者这可能是我不知道的某种反模式。 我真的不知道该问谁。(哦,是的,Shared .run (SharedRunnable r,INPUT input) 就像...
private final <OUTPUT, INPUT> OUTPUT run(final SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> r, final INPUT input) {
try {
lock.lock();
return r.run(sharedVariable, input);
} finally {
lock.unlock();
}
}
这只是我的个人实验,因此并不算完全完成,但我现在有一个不错的项目正在使用它,它确实帮了很大的忙。