我有以下Thread子类(为了易读性稍微简化):
public class ConnectionHandlerThread extends Thread {
private Socket socket;
private volatile boolean disconnected = false;
private ObjectOutputStream out = null;
private ObjectInputStream in = null;
public ConnectionHandlerThread(Socket socket){
this.socket = socket;
}
public void run(){
disconnected = false;
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
while(!disconnected){
try{
Object data = in.readObject();
}
catch(ClassNotFoundException e){
// Handle exception
}
catch(IOException e){
// Handle exception
}
}
}
catch (IOException e) {
// Handle exception
}
}
public void send(Object data){
try{
out.writeObject( data );
}
catch(IOException e){
// Handle exception
}
}
}
当我连接到服务器时,这个线程的一个实例是由我的客户端(使用Swing GUI)创建的。我觉得奇怪的是,我可以从主GUI调用方法send(Object data)
,而且它是有效的。为什么无限而循环和/或调用in.readObject()
不会阻止我这样做?我的意思是线程不应该一直忙于做其他事情吗?这是做事的好方法吗?如果不是,为什么不呢?
编辑
为了澄清我的困惑:如果这是在主线程中,它将在中的上繁忙。readObject()
直到读取了某个内容,然后它将在循环的下一次迭代中再次开始侦听。当然,我可以从另一个线程调用send()
。但让我大吃一惊的是,“谁”实际上在执行send()?是我的线程在做,还是调用线程在做?如果是前者,它怎么可能既忙着在while循环中等待输入,又忙着执行send()方法呢?我只是很难把我的思想集中在它上面。。。
这是有效的,因为在SWING/GUI中,您正在执行以下操作:
ConnectionHandlerThread myThread = ConnectionHandlerThread(new Socket());
现在,send()
方法是公共的,所以您可以在执行此操作时从GUI类调用它
myThread.send(data);
诀窍在于,您在线程中使用了一个套接字,这都是因为您在类的构造函数中传递了一个套接字
@jameslarge是的,我现在很困惑。。。
Thread
对象不是线程:它具有可用于配置、创建和与线程交互的方法。您正在使用您的ConnectionHandlerThread
来完成所有这些,并且您还使用它(通过覆盖run()
方法)来定义线程所做的工作,并且您还使用它(通过几个私有字段)来表示线程操作的连接状态。那是很多重载。
一位作者说,“编写对象太少的程序很容易。编写对象太多的程序很难。”
我将重新编写您的代码,以使用三个不同的对象来执行ConnectionHandlerThread现在执行的三个不同的作业:
public class Connection {
private Socket socket;
private volatile boolean connected = true;
private ObjectOutputStream out = null;
private ObjectInputStream in = null;
public Connection(Socket socket){
this.socket = socket;
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
}
public void send(Object data){
try{
out.writeObject( data );
}
catch(IOException e){
handleExceptionInSend(e);
}
}
public Object receive() {
try{
Object data = in.readObject();
}
catch(ClassNotFoundException e){
handleExceptionInReceive(e);
return NULL;
}
catch(IOException e){
handleExceptionInReceive(e);
return NULL;
}
return Object;
}
public boolean isConnected() {
return connected;
}
...
}
public class ConnectionListener implements Runnable {
private final connection;
public ConnectionRunner(Connection connection) {
this->connection = connection;
}
public void run(){
while(connection.isConnected()){
Object o = connection.receive();
if (o) {
doSomethingWith(o);
}
}
}
}
public class Whatever {
...
public void whateverelse( ) {
Socket socket = ...;
Connection connection = new Connection(socket);
ConnectionListener listener = new ConnectionListener(connection);
Thread connectionThread = new Thread(listener);
connectionThread.start();
...
}
...
}
连接
对象知道如何发送和接收数据。
listener
对象定义了线程的作用:即,它从连接接收对象,直到! isConnect()
并对它们执行某些操作。
最后,connectionThread对象是启动线程的对象(可以用来等待线程完成等),如果需要的话。
它比你写的代码更多,但IMO,它更容易理解,因为它更容易看到每个单独部分的职责。有时,尤其是如果您与其他开发人员合作,使代码易于理解比使其变小更重要。
有两件事:
1) 无限循环不会使cpu只对自身繁忙。它只是在它可用的时候让它保持忙碌,但我的其他线程也使用它。
2) 当你打电话给你的
发送(对象数据)
你并不是从你的线程开始做的,所以要记住1)它被调用并不奇怪
例子:
代码:
public class Main {
public static void main(String[] args) {
InfiniteThread t = new InfiniteThread();
t.start();
for(int i=0;i<10;i++) {
t.fromOut(i);
}
}
@DebugLog
public static class InfiniteThread extends Thread {
public void run() {
for(int i=0;i<10;i++) {
fromIn();
}
}
private void fromIn() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void fromOut(Object data){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
无限阅读::⇢ ()[线程:“main”]无限线程::⇠ [0ms]无限读取:⇢ run()[线程:“Thread-0”]无限线程::⇢ fromIn()[线程:“线程-0”]无限线程::⇢ fromOut(数据=0)[线程:“main”]无限读取::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(data=1)[线程:“main”]无限读取::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=2)[线程:“main”]无限读取::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=3)[线程:“main”]无限读取::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=4)[线程:“main”]无限读取::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=5)[线程:“main”]无限读取::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=6)[线程:“main”]无限读取::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=7)[线程:“main”]无限读取::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=8)[线程:“main”]无限读取::⇠ fromOut[500ms]无穷大读数:⇢ fromOut(数据=9)[线程:“main”]无限读取::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromOut[500ms]无穷大读数:⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromIn【1000ms】无穷大读数:⇢ fromIn()[线程:“线程-0”]无限线程::⇠ fromIn【1000ms】无穷大读数:⇠ 运行【10003ms】
问题内容: 有没有简单的解决方案,可以在新线程中使用JPA将数据保存到数据库中? 我基于Spring的Web应用程序允许用户管理计划的任务。在运行时,他可以创建和启动预定义任务的新实例。我正在使用spring的TaskScheduler,并且一切正常。 但是我需要将每个被激发任务的布尔结果保存到数据库中。我怎样才能做到这一点? 编辑:我必须概括我的问题:我需要从任务在我的@Service类上调用方
然而,在我下面的代码中,我希望在这两个示例中都花费相同的15秒(每个任务5秒),如本文所述。然而,第二个示例只需要5秒,同时运行所有3个示例也需要5秒来完成第二个示例。原来的文章花了5秒,但我把它改成了1秒的延迟,让它更明显。 有没有人能解释一下这是怎么回事,为什么它看起来像线程一样运行?
我目前正在深入研究多线程,但我在理解我当前在代码中做错了什么方面遇到了一些问题。 我试图通过调用我的“ThreadPopulateList()”来用随机数据填充2个列表,在我的理解中,这应该以Parralel启动2个线程。因为我调用了该方法两次。 但当我调用ThreadMethod时,执行时间会增加50%。这是为什么?如有任何帮助,我们将不胜感激!
本文向大家介绍请你来说一说Redis是单线程的,但是为什么这么高效呢?相关面试题,主要包含被问及请你来说一说Redis是单线程的,但是为什么这么高效呢?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 虽然Redis文件事件处理器以单线程方式运行,但是通过使用I/O多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与Redis服务器中其他同样以单线程运行的
例如: 假设有一个按钮启动异步请求,该请求返回并触发主线程上运行的runnable/callback。会发生什么?runnable被添加到MessageQueue中,并在“时间”到时运行。但是什么时候是“时间”呢?如果在异步请求将runnable发布到MainThread之前,我按下另一个按钮,在MainThread上执行一些半长的阻塞任务呢?它会等到我的阻塞按钮上的逻辑完成吗?会打断它吗?它是否
这是我的密码 结果为上述结果之一。从调用仍然调用子类的,即使从词汇上讲,meth调用在超类内部!那么,当是私有的时候,为什么会有不同的行为呢? ___________edit____________ 代码是这样的吗 O/P将是 因此,即使超级类中的正在调用,但实际上子类的正在被调用。所以,方法调用不是词法意义上的!也就是说,即使看起来将调用超级类的meth,实际上它的子类的becoz子类实例首先调