大多数并发应用程序是围绕执行任务进行管理的。所谓任务就是抽象,离散的工作单元。
围绕执行任务进行管理应用程序最重要的就是要指明一个清晰的任务边界。
大多数的服务器应用程序都选择自然的任务边界:单独的客户请求。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并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
10. **Java并发编程**:包括线程池、锁机制(如synchronized、ReentrantLock)、并发容器(如ConcurrentHashMap、CopyOnWriteArrayList)以及并发工具类(如CountDownLatch、CyclicBarrier)。 这些是Java基础知识...
Java JDK 6学习笔记是为Java初学者量身定制的一份宝贵资料,它涵盖了Java编程的基础概念、语法以及核心特性。这份PPT简体版旨在帮助读者快速掌握Java开发的基本技能,逐步成为一名合格的Java程序员。 Java JDK...
这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...
集合框架是Java编程语言中的核心组成部分,它提供了一套高效、灵活的数据结构和算法操作,使得程序员能够方便地存储和管理对象。这篇学习笔记将深入探讨Java集合框架的基础概念、主要类库以及常见应用场景。 首先,...
《良葛格的Java学习笔记》是一本专为Java初学者设计的教程,作者林信良深入浅出地讲解了Java编程的基础知识。这本笔记覆盖了Java学习的重要概念,包括但不限于以下几个方面: 1. **Java简介**:Java是一种跨平台、...
多线程是Java并发编程的基础,本章探讨了如何在Java中创建与管理线程,理解线程生命周期,以及如何实现线程同步与通信,提高程序的执行效率与响应速度。 #### 第六章:常用类API 本章涵盖了Java标准库中的重要类与...
下面,我们将深入探讨Java的基础知识,涵盖核心概念、语法和编程实践。 1. **Java简介**:Java是由Sun Microsystems公司(现已被Oracle收购)开发的一种面向对象的编程语言,具有“一次编写,到处运行”的特性。它...
这份笔记集合了Java编程语言的基础知识,旨在帮助读者从零开始掌握这门广泛使用的编程语言。以下是对笔记中涉及的主要知识点的详细阐述: 1. **Java简介**:Java是由Sun Microsystems公司开发的面向对象的编程语言...
理解同步、互斥、死锁等并发编程概念,以及synchronized关键字、wait/notify机制的使用,是编写高效并发程序的关键。 7. **反射机制**:Java的反射机制允许程序在运行时动态地获取类的信息并操作类的对象,这是许多...
6. **第六天 笔记.doc**:最后一天的课程可能深入到Java企业级应用开发,比如Spring框架、Maven项目管理工具、JUnit测试框架的使用,或者涉及EJB、JMS、Servlet和JSP等Web开发技术。 这些笔记可能还包括实际案例...
Java语言程序设计学习笔记是为初学者和有一定基础的开发者准备的一份详尽教程,它涵盖了从基础到进阶的各个重要知识点...这份学习笔记不仅覆盖了基础语法,还包括了一些高级特性和最佳实践,是一份全面的Java学习资源。
第六,笔记可能还涉及到了Java网络编程,如Socket通信、HTTP客户端服务器实现,以及NIO(非阻塞I/O)的使用,这些都是Java在分布式系统中常见的问题领域。 第七,数据库连接池的使用,如C3P0、HikariCP、Druid等,...
本资源“21天学Java培训笔记和代码”旨在帮助初学者在短时间内掌握Java核心概念,通过实践和理论相结合的方式提升学习效率。这份资料包含的文件很可能是每日学习计划的总结,包括关键知识点的笔记和相应的示例代码。...
这份名为"Corejava 核心java笔记"的资料应该包含了作者在学习Java基础时的一些理解和实践心得,对于初学者来说是一份宝贵的参考资料。 1. **Java语法**: Java语法简洁而严谨,包括变量声明、数据类型(如整型、浮点...
Java 6学习笔记是针对初学者和有一定经验的开发者提供的一份全面的教育资源,它涵盖了Java编程语言的基础到高级概念。这份笔记旨在帮助读者深入理解Java 6的关键特性,提高编程技能,并为实际项目开发打下坚实基础。...
6-第六天-魔乐java基础视频学习笔记.docx:可能会涵盖集合框架,如ArrayList、LinkedList、HashSet和HashMap等,这些都是处理数据集合的重要工具。 9-第二十天-魔乐java基础视频学习笔记.docx:可能涉及线程和并发...