第六章读书笔记
大多数并发应用程序是围绕执行任务进行管理的。所谓任务就是抽象,离散的工作单元。
围绕执行任务进行管理应用程序最重要的就是要指明一个清晰的任务边界。
大多数的服务器应用程序都选择自然的任务边界:单独的客户请求。Web服务器,邮件服务器,文件服务器,EJB容器和数据库服务器。这些服务器都接受远程客户通过网络连接发送的请求。
应用服务器内部的调度策略:
1)顺序的执行
class SingleThreadWebServer{
public static void main(String[] args) throws IOException{
ServerSocket socket = new ServerSocket(80);
while(true){
Socket connetion = socket.accept();
handleRequest(connection);
}
}
}
2)显式地为任务创建线程
class ThreadPerTaskWebServer { public static void main(String[] args) throws IOException { ServerSocket socket = new ServerSocket(80); while (true) { final Socket connection = socket.accept(); Runnable task = new Runnable() { public void run() { handleRequest(connection); } }; new Thread(task).start(); } } }
无限制创建线程的缺点:
1)线程的创建销毁本身的开销
2)活动线程会消耗系统资源,尤其是内存
3)稳定性
Executor框架
executor只是一个简单的接口,但它却为一个灵活而且强大的框架创造了基础,这个框架可以用于异步执行,而且
支持很多不同类型的任务执行策略。他还为任务提交和任务执行之间的解耦提供了标准的方法,为使用Runnable描述任务提供了通用的方式。Executor的实现还提供了对生命周期的支持以及钩子函数,可以添加诸如统计收集,应用程序管理
机制和监视器等扩展。
Executor基于生产者-消费者模式。
使用Executor实现的Web Server
class TaskExecutionWebServer { private static final int NTHREADS = 100; private static final Executor exec = Executors.newFixedThreadPool(NTHREADS); public static void main(String[] args) throws IOException { ServerSocket socket = new ServerSocket(80); while (true) { final Socket connection = socket.accept(); Runnable task = new Runnable() { public void run() { handleRequest(connection); } }; exec.execute(task); } } } |
Executor将任务的请求和执行进行了解耦,只要替换一个不同的Executor实现,就可以改变服务器的行为。
public class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
};
}
public class WithinThreadExecutor implements Executor { public void execute(Runnable r) { r.run(); }; } |
Executors提供了一些静态方法用来创建线程池
newSingleThreadExecutor: 产生一个 ExecutorService 对象,这个对象只有一个线程可用来执行任务,若任务多于一个,任务将按任务队列规定的顺序(FIFO,LIFO,优先级)执行。 如果一个现场异常关闭,会有新的来补充
newCachedThreadPool(): 产生一个 ExecutorService 对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用。
newFixedThreadPool(int poolSize) :产生一个 ExecutorService 对象,这个对象带有一个大小为 poolSize 的线程池,若任务数量大于 poolSize ,任务会被放在一个 queue 里顺序执行。
newSingleThreadScheduledExecutor :产生一个 ScheduledExecutorService 对象,这个对象的线程池大小为 1 ,若任务多于一个,任务将按先后顺序执行。
newScheduledThreadPool(int poolSize): 产生一个 ScheduledExecutorService 对象,这个对象的线程池大小为 poolSize ,若任务数量大于 poolSize ,任务会在一个 queue 里等待执行
Excetor的生命周期
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
public class LifecycleWebServer
{
private final ExecutorService exec = Executors.newSingleThreadExecutor();
public void start()
{
// while (true)//实验中这两个效果是一样的
while (!exec.isShutdown())
{
try
{
final String requestId = Client.request();
exec.execute(new Runnable()
{
public void run()
{
handleRequest(requestId);
}
});
Thread.sleep(1000);
}
catch (RejectedExecutionException e)
{
if (!exec.isShutdown())
{
System.out.println("task submission rejected" + e.toString());
}
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void stop()
{
exec.shutdown();
}
public void handleRequest(String requestId)
{
if (requestId.equals("stop"))
{
stop();
}
else
{
System.out.println("我打印了" + requestId);
}
}
}
public class Client
{
public static void main(String[] args)
{
Runnable run = new Runnable()
{
public void run()
{
while (true)
{
putRequest();
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
new Thread(run).start();
LifecycleWebServer server = new LifecycleWebServer();
server.start();
}
public static String request = "stopstopstop";
public static String request()
{
return request;
}
public static void putRequest()
{
request = request.substring(0, request.length() - 1);
System.out.println("我修改了" + request);
}
}
上一篇: 关于java的一些理解