并发--基本的线程机制
1. 基本概念
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
线程是独立调度和分派的基本单位。线程可以为操作系统内核调度的内核线程,如Win32线程;由用户进程自行调度的用户线程,如Linux平台的POSIX Thread;或者由内核与用户进程,如Windows 7的线程,进行混合调度。
同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。
在多核或多 CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率。(摘自百度百科)
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。
当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。
非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。
2 定义任务
线程可以驱动任务,因此需要一种描述任务的方式。创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。
2.1 重写Thread类的的run方法
public class Thread extends Object implements Runnable
查看 API文档可知:其实 Thread 也是实现 Runable 接口的类
1 package thread; 2 3 public class liftOff implements Runnable { 4 protected int countDown=10; 5 private static int taskCount=0; 6 private final int id=taskCount++; 7 public liftOff() {} 8 public liftOff(int countDown) { 9 this.countDown=countDown; 10 } 11 public String status() { 12 return "#"+id+"("+(countDown>0?countDown:"liftOff")+"),"; 13 } 14 @Override 15 public void run() { 16 // TODO Auto-generated method stub 17 while(countDown-->0) { 18 System.out.print(status()); 19 Thread.yield(); 20 } 21 } 22 23 }
package thread;public class basicThread {public static void main(String[] args){Thread t=new Thread(new liftOff());t.start();System.out.println("Waiting for liftOFF");} }//Output /*#0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(liftOff),#1(9),#1(8),#1(7),#1(6),#1(5),#1(4),#1(3),#1(2),#1(1),#1(liftOff),#2(9),#2(8),#2(7),#2(6),#2(5),#2(4),#2(3),#2(2),#2(1),#2(liftOff),#3(9),#3(8),#3(7),#3(6),#3(5),#3(4),#3(3),#3(2),#3(1),#3(liftOff),#4(9),#4(8),#4(7),#4(6),#4(5),#4(4),#4(3),#4(2),#4(1),#4(liftOff),*/
View Code
2.2 声明实现 Runnable 接口
1 package thread; 2 3 public class mainThread { 4 public static void main(String[] args) { 5 liftOff launch=new liftOff(); 6 launch.run(); 7 } 8 } 9 /* Output #0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(liftOff), 10 */
从运行结果可以看出,并发是每个线程是互不影响的。
异步时,new Thread的弊端如下:
a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
相比new Thread,Java提供的四种线程池的好处在于:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。
2.3 使用 Executor接口
执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。
不过,Executor 接口并没有严格地要求执行是异步的。在最简单的情况下,执行程序可以在调用者的线程中立即运行已提交的任务: 更常见的是,任务是在某个不是调用者线程的线程中执行的。以下执行程序将为每个任务生成一个新线程。
许多 Executor 实现都对调度任务的方式和时间强加了某种限制。以下执行程序使任务提交与第二个执行程序保持连续,这说明了一个复合执行程序。
此包中提供的 Executor 实现实现了 ExecutorService,这是一个使用更广泛的接口。ThreadPoolExecutor 类提供一个可扩展的线程池实现。Executors 类为这些 Executor 提供了便捷的工厂方法。
内存一致性效果:线程中将 Runnable 对象提交到 Executor 之前的操作 happen-before 其执行开始(可能在另一个线程中)。
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
1)使用CachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:
1 package thread; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 public class cachedThreadPool { 7 public static void main(String[] args) { 8 ExecutorService exec = Executors.newCachedThreadPool(); 9 for (int i = 0; i < 5; i++) { 10 exec.execute(new liftOff()); 11 } 12 exec.shutdown(); 13 14 } 15 }/*Output #1(9),#0(9),#1(8),#0(8),#3(9),#4(9),#2(9),#0(7),#2(8),#3(8),#0(6),#1(7),#0(5),#3(7),#0(4),#2(7),#4(8),#1(6),#3(6),#2(6),#4(7),#1(5),#3(5),#1(4),#2(5),#0(3),#4(6),#3(4),#1(3),#2(4),#0(2),#4(5),#1(2),#2(3),#1(1),#3(3),#2(2),#4(4),#0(1),#1(liftOff),#2(1),#0(liftOff),#3(2),#2(liftOff),#4(3),#3(1),#4(2),#3(liftOff),#4(1),#4(liftOff), 16 */
2)使用FixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
1 package thread; 2 3 4 5 import java.util.concurrent.ExecutorService; 6 import java.util.concurrent.Executors; 7 8 public class fixedThreadPool { 9 public static void main(String[] args) { 10 ExecutorService exec = Executors.newFixedThreadPool(5); 11 for (int i = 0; i < 5; i++) { 12 exec.execute(new liftOff()); 13 } 14 exec.shutdown(); 15 16 } 17 } 18 /*Output #1(9),#0(9),#1(8),#0(8),#3(9),#4(9),#2(9),#0(7),#2(8),#3(8),#0(6),#1(7),#0(5),#3(7),#0(4),#2(7),#4(8),#1(6),#3(6),#2(6),#4(7),#1(5),#3(5),#1(4),#2(5),#0(3),#4(6),#3(4),#1(3),#2(4),#0(2),#4(5),#1(2),#2(3),#1(1),#3(3),#2(2),#4(4),#0(1),#1(liftOff),#2(1),#0(liftOff),#3(2),#2(liftOff),#4(3),#3(1),#4(2),#3(liftOff),#4(1),#4(liftOff), 19 20 * */
3)使用SingleThreadPool
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:
package thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class singleThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
exec.execute(new liftOff());
}
exec.shutdown();
}
}/*#0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(liftOff),
#1(9),#1(8),#1(7),#1(6),#1(5),#1(4),#1(3),#1(2),#1(1),#1(liftOff),
#2(9),#2(8),#2(7),#2(6),#2(5),#2(4),#2(3),#2(2),#2(1),#2(liftOff),
#3(9),#3(8),#3(7),#3(6),#3(5),#3(4),#3(3),#3(2),#3(1),#3(liftOff),
#4(9),#4(8),#4(7),#4(6),#4(5),#4(4),#4(3),#4(2),#4(1),#4(liftOff),
*/
转载于:https://www.cnblogs.com/tianliang94/p/10633797.html
并发--基本的线程机制相关推荐
- 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )
文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...
- 【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )
文章目录 前言 一.线程池示例 二.newCachedThreadPool 线程池示例 三.newFixedThreadPool 线程池示例 三.newSingleThreadExecutor 线程池 ...
- 探索 ConcurrentHashMap 高并发性的实现机制
简介 ConcurrentHashMap 是 util.concurrent 包的重要成员.本文将结合 Java 内存模型,分析 JDK 源代码,探索 ConcurrentHashMap 高并发的具体 ...
- Java并发编程之线程池及示例
1.Executor 线程池顶级接口.定义方法,void execute(Runnable).方法是用于处理任务的一个服务方法.调用者提供Runnable 接口的实现,线程池通过线程执行这个 Runn ...
- 探索 ConcurrentHashMap 高并发性的实现机制--转
ConcurrentHashMap 是 Java concurrent 包的重要成员.本文将结合 Java 内存模型,来分析 ConcurrentHashMap 的 JDK 源代码.通过本文,读者将了 ...
- 并发编程-11线程安全策略之线程封闭
文章目录 脑图 概述 线程封闭的三种方式 示例 堆栈封闭 ThreadLocal Step1. ThreadLocal操作类 Step2. 自定义过滤器 Step3. 注册拦截器,配置拦截规则 Ste ...
- c++ 线程池_基础篇:高并发一瞥,线程和线程池的总结
进程是执行程序的实体,拥有独属的进程空间(内存.磁盘等).而线程是进程的一个执行流程,一个进程可包含多个线程,共享该进程的所有资源:代码段,数据段(全局变量和静态变量),堆存储:但每个线程拥有自己的执 ...
- java并发编程与线程安全
2019独角兽企业重金招聘Python工程师标准>>> 什么是线程安全 如果对象的状态变量(对象的实例域.静态域)具有可变性,那么当该对象被多个线程共享时就的考虑线程安全性的问题,否 ...
- Java线程机制学习
前面的文章中总结过Java中用来解决共享资源竞争导致线程不安全的几种常用方式: synchronized: ReentrantLock: ThreadLocal: 这些都是在简单介绍了基本用法的基础上 ...
最新文章
- rsyslog的配置文件使用方法
- 车路协同让城市更智慧
- python 散点图_Python绘制散点图
- Android 插件技术实战总结
- JMS : Java Message Service (Java消息服务)之一 [转]
- java按比例之原图生成缩略图
- 6月国产网络游戏审批信息公布 共计86款游戏过审
- 【CS231n_2017】2-Image Classification
- HttpWebRequest中GetResponse或者说GetRequestStream偶尔超时,或者是各种操作超时造成的假死的一些解决方案...
- 做一款仿映客的直播App
- SVM笔记(一)硬间隔SVM
- google crx Hoxx 下载
- 计算机技术三大领域,量化投资策略的运用
- antd 踩坑之 javascriptEnabled配置
- C5750X7R2E105K230KA(电容器)MSP430F5249IRGCR微控制器资料
- Beyong Compare使用
- 我是没有志气的程序员
- LK32T102简述
- neat算法做监督学习(Python)
- 计算机主要配件型号价格,你知道电脑的“五大主要部件”的选择吗?
热门文章
- Git 服务器镜像迁移 - 携带提交日志,tag,branch。。
- Selenium Web 自动化 - Selenium常用API
- 转;说说AngularJS中的$parse和$eval
- Docker容器的原理与实践(上)
- JavaScript 工作原理之十一-渲染引擎及性能优化小技巧
- c++11 线程:让你的多线程任务更轻松
- 数据结构之链表、栈和队列 java代码实现
- application/x-www-form-urlencoded multipart/form-data text/plain 的区别和作用
- 比特币现金(BCH)将在2018年占据主导地位
- es6之扩展运算符...