GuardedSuspention(二)

xiaoxiao2026-08-12  43

服务器线程在红色部分可能会阻塞,也就是说,Queue.getRequest是一个阻塞方法。这和java标准库的许多IO方法类似。 最后,写一个Main来启动他们: package com.crackj2ee.thread; public class Main { public static void main(String[] args) { Queue queue = new Queue(); ServerThread server = new ServerThread(queue); server.start(); ClientThread[] clients = new ClientThread[5]; for(int i=0; i<clients.length; i++) { clients[i] = new ClientThread(queue, ""+i); clients[i].start(); } try { Thread.sleep(100000); } catch(InterruptedException ie) {} server.shutdown(); } } 我们启动了5个客户端线程和一个服务器线程,运行结果如下: [ClientThread-0] send request: Request-4984 [ServerThread] handle request: Request-4984 [ClientThread-1] send request: Request-2020 [ClientThread-2] send request: Request-8980 [ClientThread-3] send request: Request-5044 [ClientThread-4] send request: Request-548 [ClientThread-4] send request: Request-6832 [ServerThread] handle request: Request-2020 [ServerThread] handle request: Request-8980 [ServerThread] handle request: Request-5044 [ServerThread] handle request: Request-548 [ClientThread-4] send request: Request-1681 [ClientThread-0] send request: Request-7859 [ClientThread-3] send request: Request-3926 [ServerThread] handle request: Request-6832 [ClientThread-2] send request: Request-9906 ...... 可以观察到ServerThread处理来自不同客户端的请求。 思考 Q: 服务器线程的wait条件while(queue.size()==0)能否换成if(queue.size()==0)? A: 在这个例子中可以,因为服务器线程只有一个。但是,如果服务器线程有多个(例如Web应用程序有多个线程处理并发请求,这非常普遍),就会造成严重问题。 Q: 能否用sleep(1000)代替wait()? A: 绝对不可以。sleep()不会释放锁,因此sleep期间别的线程根本没有办法调用getRequest()和putRequest(),导致所有相关线程都被阻塞。 Q: (Request)queue.remove(0)可以放到synchronized() {}块外面吗? A: 不可以。因为while()是测试queue,remove()是使用queue,两者是一个原子操作,不能放在synchronized外面。 总结 多线程设计看似简单,实际上必须非常仔细地考虑各种锁定/同步的条件,稍不小心,就可能出错。并且,当线程较少时,很可能发现不了问题,一旦问题出现又难以调试。 所幸的是,已有一些被验证过的模式可以供我们使用,我们会继续介绍一些常用的多线程设计模式。
转载请注明原文地址: https://www.6miu.com/read-5051072.html

最新回复(0)