一、概念

1.进程:一个具有一定独立功能的程序,关于某些数据集合,一次运行活动。 两点:1、有自己的空间存储数据;2、一个程序。  

   进程,是系统   进行   资源分配  和 调度  的基础单位。动态性,独立性,并发性,异步性,结构特征(程序、数据、进程控制块)

   进程控制块,为  管理进程  而设置的数据结构,用于描述进程过程或者进程状态的变化过程。包括:程序计数器(指令地址)、CPU暂存器(累加器、堆栈指针)等等

2. 线程:程序执行的最小单位;单一顺序控制流程;

  通常,一个进程包含多个线程,进程:资源分配,线程:独立运行、独立调度;

二、状态

1. 新建状态(New):新创建了一个线程对象。

2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

sleep与wait的区别

1、所属类:sleep是thread的方法;wait是Object的方法;

2、锁释放:sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法;

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常;

三、线程的使用

1、多线程的实现方式--无返参

 public abstract interface Runnable
{
public abstract void run();
}

实现接口Runnable:重写run()方法,封装Thread类,并通过start()方法实现线程的启动。

 public class Thread  implements Runnable

继承父类Thread:重写run()方法,实例化对象并调用start()方法,即可实现线程的启动。

而start()方法,由jvm识别并调用run()方法。

java类仅仅支持继承一个父类,但是可以实现多个接口,所以,尽量以Runnable接口的形式实现多线程。

多次调用同一线程对象的start()方法,会报错提示IllegalThreadStateException

2、多线程的实现方式--有返参

带返参的线程

 public interface Callable<V> {
V call() throws Exception;
}

实现接口Callable:重写call方法

扩展接口:Future:get等方法,RunnableFuture:继承两个接口Runnable 和Future;

实现类FutureTask :实现RunnableFuture

 public abstract interface Future<V>
{
public abstract boolean cancel(boolean paramBoolean); public abstract boolean isCancelled(); public abstract boolean isDone(); public abstract V get()
throws InterruptedException, ExecutionException; public abstract V get(long paramLong, TimeUnit paramTimeUnit)
throws InterruptedException, ExecutionException, TimeoutException;
}

RunnableFuture接口

 public abstract interface RunnableFuture<V> extends Runnable, Future<V>
{
public abstract void run();
}

FutureTask

 Callable<String> callable = new CallableImpl("my callable test!");
FutureTask<String> task = new FutureTask<>(callable);
new Thread(task).start();
String result = task.get();

3、线程池--生产者消费者模式

概念:综合管理线程,减少处理器的闲置时间,提高服务性能 ;尤其应用于场景:创建线程时间+销毁线程时间>线程运行时间;

Executor 是 Java 线程池的核心接口,用来并发执行提交的任务;提供execute()方法用来提交任务;无返参;不支持取消;

 public abstract interface Executor
{
public abstract void execute(Runnable paramRunnable);
}

ExecutorService 是 Executor 接口的扩展,提供了异步执行和关闭线程池的方法;提供submit()方法用来提交任务; submit()方法可以接受RunnableCallable接口的对象;Future对象可以实现线程的取消和返参获取;shutDown()方法关闭线程池;

 public abstract interface ExecutorService extends Executor
{
public abstract void shutdown(); public abstract List<Runnable> shutdownNow(); public abstract boolean isShutdown(); public abstract boolean isTerminated(); public abstract boolean awaitTermination(long paramLong, TimeUnit paramTimeUnit)
throws InterruptedException; public abstract <T> Future<T> submit(Callable<T> paramCallable); public abstract <T> Future<T> submit(Runnable paramRunnable, T paramT); public abstract Future<?> submit(Runnable paramRunnable); public abstract <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> paramCollection)
throws InterruptedException; public abstract <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> paramCollection, long paramLong, TimeUnit paramTimeUnit)
throws InterruptedException; public abstract <T> T invokeAny(Collection<? extends Callable<T>> paramCollection)
throws InterruptedException, ExecutionException; public abstract <T> T invokeAny(Collection<? extends Callable<T>> paramCollection, long paramLong, TimeUnit paramTimeUnit)
throws InterruptedException, ExecutionException, TimeoutException;
}

Executors 是一个工具类;提供工厂方法来创建不同类型的线程池;

Executor vs ExecutorService vs Executors

正如上面所说,这三者均是 Executor 框架中的一部分。Java 开发者很有必要学习和理解他们,以便更高效的使用 Java 提供的不同类型的线程池。总结一下这三者间的区别,以便大家更好的理解:

  • Executor 和 ExecutorService 这两个接口主要的区别是:ExecutorService 接口继承了 Executor 接口,是 Executor 的子接口
  • Executor 和 ExecutorService 第二个区别是:Executor 接口定义了 execute()方法用来接收一个Runnable接口的对象,而 ExecutorService 接口中的 submit()方法可以接受RunnableCallable接口的对象。
  • Executor 和 ExecutorService 接口第三个区别是 Executor 中的 execute() 方法不返回任何结果,而 ExecutorService 中的 submit()方法可以通过一个 Future 对象返回运算结果。
  • Executor 和 ExecutorService 接口第四个区别是除了允许客户端提交一个任务,ExecutorService 还提供用来控制线程池的方法。比如:调用 shutDown() 方法终止线程池。可以通过 《Java Concurrency in Practice》 一书了解更多关于关闭线程池和如何处理 pending 的任务的知识。
  • Executors 类提供工厂方法用来创建不同类型的线程池。比如: newSingleThreadExecutor() 创建一个只有一个线程的线程池,newFixedThreadPool(int numOfThreads)来创建固定线程数的线程池,newCachedThreadPool()可以根据需要创建新的线程,但如果已有线程是空闲的会重用已有线程。

4种类型的线程池

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

   // 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
// 创建线程
Thread t1 = new MyThread();
Thread t2 = new MyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
// 关闭线程池
pool.shutdown();
 public class FutureTaskExample {
public static void main(String[] args) {
MyCallable callable1 = new MyCallable(1000); // 要执行的任务
MyCallable callable2 = new MyCallable(2000); FutureTask<String> futureTask1 = new FutureTask<String>(callable1);// 将Callable写的任务封装到一个由执行者调度的FutureTask对象
FutureTask<String> futureTask2 = new FutureTask<String>(callable2); ExecutorService executor = Executors.newFixedThreadPool(2); // 创建线程池并返回ExecutorService实例
executor.execute(futureTask1); // 执行任务
executor.execute(futureTask2); while (true) {
try {
if(futureTask1.isDone() && futureTask2.isDone()){// 两个任务都完成
System.out.println("Done");
executor.shutdown(); // 关闭线程池和服务
return;
} if(!futureTask1.isDone()){ // 任务1没有完成,会等待,直到任务完成
System.out.println("FutureTask1 output="+futureTask1.get());
} System.out.println("Waiting for FutureTask2 to complete");
String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
if(s !=null){
System.out.println("FutureTask2 output="+s);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}catch(TimeoutException e){
//do nothing
}
}
}
}


JAVA总结--多线程的更多相关文章

  1. Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  2. java之多线程 二

    线程的生命周期: 当线程被创建并被启动时,它既不是一启动就进入了执行状态,在线程的生命周期中,它要经过new(新建),就绪(Runnable),运行(Running),阻塞(Blocked),dead ...

  3. Java的多线程机制系列:(一)总述及基础概念

    前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...

  4. Java Thread 多线程 介绍

    1.线程概述 几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程. 当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程. 2.线程 ...

  5. Java:多线程<一>

    程序运行时,其实是CPU在执行程序的进程,为了提高工作效率一个进程可以有多个线程. Java的多线程: 其实我们之前就见过Java的线程,main就是Java的一个线程,还有另一个条线程总是和main ...

  6. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  7. Java的多线程机制系列:(三)synchronized的同步原理

    synchronized关键字是JDK5之实现锁(包括互斥性和可见性)的唯一途径(volatile关键字能保证可见性,但不能保证互斥性,详细参见后文关于vloatile的详述章节),其在字节码上编译为 ...

  8. Java基础——多线程

    Java中多线程的应用是非常多的,我们在Java中又该如何去创建线程呢? http://www.jianshu.com/p/40d4c7aebd66 一.常用的有三种方法来创建多线程 新建一个类继承自 ...

  9. JAVA之多线程的创建

    转载请注明源出处:http://www.cnblogs.com/lighten/p/5967853.html 1.概念 老调重弹,学习线程的时候总会牵扯到进程的概念,会对二者做一个区分.网上有较多的解 ...

  10. Java基础--多线程的方方面面

    1,什么是线程?线程和进程的区别是什么? 2,什么是多线程?为什么设计多线程? 3,Java种多线程的实现方式是什么?有什么区别? 4,线程的状态控制有哪些方法? 5,线程安全.死锁和生产者--消费者 ...

随机推荐

  1. 10年前文章_fedora10root登录

    fedora10系统root用户登录以及普通用户使用sudo命令1.问题:fedora10默认不能够直接用root用户登录解决方法:我们可以先以普通用户登录$su#vi /etc/pam.d/gdm删 ...

  2. 转 Nacos集群环境搭建

    转载 送上nacos-server-1.1.3 链接:https://pan.baidu.com/s/11r3OeffHN8AwKLurmmzJmg  密码:wdu2 下载↓↓↓↓ https://g ...

  3. 题解 P3166 【[CQOI2014]数三角形】

    做完之后看了看题解,怎么一篇和我思路一样的也没有...我好慌啊qwq(所以一定是窝太弱了看不懂dalao的思路) 好吧窝的方法确实很奇怪: 核心代码只有3行 输入 循环 输出 一气呵成 是题解中的豪杰 ...

  4. ubuntu 14.04 安装openjdk 8

    最近准备在ubuntu14.04上安装Oracle,但是需要提前安装jdk,发现问题挺多的,后面看到了如下的操作步骤,成功安装,特意记录下来. 致谢:https://www.yangshenglian ...

  5. 自己动手实现一个网络模型 python

    转自:https://www.jianshu.com/p/4b30e1dd2252 common_funcs.py import numpy as np import matplotlib.pyplo ...

  6. 阿里云 Serverless 应用引擎(SAE)发布 v1.2.0,支持一键启停、NAS 存储、小规格实例等实用特性

    近日,阿里云 Serverless 应用引擎(SAE)发布 v1.2.0版本,新版本实现了以下新功能/新特性: 一键启停开发测试环境:企业开发测试环境一般晚上不常用,长期保有应用实例,闲置浪费很高.使 ...

  7. POJ 3061 Subsequence ( 二分 || 尺取法 )

    题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用 ...

  8. Spring Cloud架构教程 (八)消息驱动的微服务(消费组)【Dalston版】

    使用消费组实现消息消费的负载均衡 通常在生产环境,我们的每个服务都不会以单节点的方式运行在生产环境,当同一个服务启动多个实例的时候,这些实例都会绑定到同一个消息通道的目标主题(Topic)上. 默认情 ...

  9. D. Shortest Cycle

    D. Shortest Cycle A[i]&A[j]!=0连边, 求图中最小环 N>128 时必有3环 其他暴力跑 folyd最小环 #include<bits/stdc++.h ...

  10. H-ui.admin v3.1学习之路(一):导航栏信息无法在内容区显示

    注:我使用的是别人的模板文件在我的云盘“素材模板—H-ui.admin’中. 直接上代码: <li class="dropDown dropDown_hover"> & ...