多线程及Thread类、Runnable接口
进程与线程
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.
1.一个程序至少有一个进程,一个进程至少有一个线程。
2.线程的划分尺度小于进程,使得多线程程序的并发性高。
3.进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4.线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5.从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。1-10 默认5
守护线程与非守护线程
守护线程是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。
关于守护线程的说法,正确的是:
A.所有非守护线程终止,即使存在守护线程,进程运行终止
B.所有守护线程终止,即使存在非守护线程,进程运行终止
C.只要有守护线程或者非守护线程其中之一存在,进程就不会终止
D.只要所有的守护线程和非守护线程终止运行之后,进程才会终止
守护线程与非守护线程并不是固定的,Thread类setDaemo属性可控制。daemo是Thread的私有属性,默认为false(非守护线程)。setDaemo必须在Thread.start()之前设置,否则会抛出一个IllegalThreadStateException异常,
public class Thread implements Runnable {private boolean daemon = false;
当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main
方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
- 调用了
Runtime
类的exit
方法,并且安全管理器允许退出操作发生。 - 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到
run
方法之外的异常。
创建新执行线程有两种方法:
1.一种方法是将类声明为 Thread
的子类,该子类应重写 Thread
类的 run
方法。接下来可以分配并启动该子类的实例。
class PrimeThread extends Thread {public void run() { . . .}}//启动线程PrimeThread p = new PrimeThread(143);p.start();
需要注意:一个Thread对象只能调用一次start方法,之后调用报错IllegalThreadStateException。主要因为执行一次后线程状态改变
2.另一种方法是声明实现 Runnable
接口的类,该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动
class PrimeRun implements Runnable {public void run() { . . .}}//启动线程PrimeRun p = new PrimeRun(143);new Thread(p).start(); new Thread(p).start();
每个线程都有一个标识名,多个线程可以同名p,同一对象启动多个线程,实现资源共享。如果线程创建时没有指定标识名,就会为其生成一个新名称,也就是新的对象,资源不共享。
两种方法的区别
1.java不允许多继承,所以实现接口Runnable比继承Thread类有明显优势,避免了单继承的局限性。
2.Runnable更容易实现资源共享,能多个线程同时处理一个资源。
Thread实现了接口Runnable,调用Start方法中会调用run方法,Runnable没有start方法所以需要Thread实例开启线程。
线程状态
New:新创建
Runnable:可运行
Blocked:阻塞
Waiting:等待
Timed Waiting:计时等待
Terminated:被终止
线程有上述6种状态,调用getState方法可确定当前状态。
对象锁:synchronized
synchronize是对象锁关键字,可修饰方法与代码块。锁的作用范围是{}内代码。锁定对象如下:
修饰方法时:修饰类方法和静态方法
修饰类方法:锁对象是调用当前方法的对象this。如果是当前对象.class的其他实例对象就是另外一个对象了不存在同步问题,即不会发生死锁。
修饰静态方法:锁对象是当前class的所有实例对象。
修饰代码块时:synchronized(Object obj) obj参数:实例对象与class对象 注意:不能是基础类型,
实例对象(this):锁对象this对象
class对象(this.class):this.class的所有对象
每一个对象都有一把锁。两个方法synchronized,顺序执行
未经考证:记录下自己的理解,synchronized(this) 锁的对象是this,springbean默认是单例的所以this不会变,到synchronized(this){}时,多线程变单线程了。如果把springbean scope改成Prototype,synchronized(this)就无效了还是多线程,这个时候改成synchronized(this.class)变单线程了
synchronized死锁的实现
package com.my.thread; /*** 死锁的实现:synchronized代码块* * */ public class ThreadDeadLock implements Runnable {private int flag = 0;private static Object numA = new Object();private static Object numB = new Object();@Overridepublic void run() {if (flag == 0) {synchronized (numA) {System.out.println(flag + "----" + numA);synchronized (numB) {System.out.println(flag + "----" + numB);}}} else if (flag == 1) {synchronized (numB) {System.out.println(flag + "----" + numB);synchronized (numA) {System.out.println(flag + "----" + numA);}}}}public static void main(String[] args) {ThreadDeadLock tt1 = new ThreadDeadLock();ThreadDeadLock tt2 = new ThreadDeadLock();tt2.flag = 1;new Thread(tt1).start();new Thread(tt2).start();} }
package com.my.thread; /*** 死锁的实现:synchronized方法* * */ public class ThreadDeadLockV1 implements Runnable, ThreadDead {private ThreadDead threadDead;public ThreadDeadLockV1() {}public ThreadDeadLockV1(ThreadDead threadDead) {this();this.threadDead = threadDead;}public void setThreadDead(ThreadDead threadDead) {this.threadDead = threadDead;}public synchronized void change1() {System.out.println(Thread.currentThread().getName() + "-change1 start");threadDead.change2();System.out.println(Thread.currentThread().getName() + "-change1 end");}public synchronized void change2() {System.out.println(Thread.currentThread().getName() + "-change2 start");threadDead.change1();System.out.println(Thread.currentThread().getName() + "-change2 end");}@Overridepublic void run() {change1();}public static void main(String[] args) {ThreadDeadLockV1 lock1 = new ThreadDeadLockV1();ThreadDeadLockV1 lock2 = new ThreadDeadLockV1(lock1);lock1.setThreadDead(lock2);new Thread(lock1).start();new Thread(lock2).start();} }
线程锁:synchronized&lock的区别
1.synchronized是一个关键字,而lock是一个类.
2.synchronized待修饰代码结束会自动释放锁,而lock需要代码释放,lock.unlock().
3.sysnchronized锁的状态无法判断,lock用方法trylock()可判断锁的状态
监视器
1.只包含有私有域的类
2.每个监视器的类都有一个相关的锁
3.使用该锁对所有方法加锁,
4.该锁可以有任意相关条件
变量可见性关键字volatile
volatile为实例域的同步访问提供了一种免锁机制。volatile不能确保原子性。所有在对volatile变量进行操作的时候要保证其操作是原子性,否则就要加锁来保证原子性.
使用volatile修饰的变量,编译器会保证其有序性,确保当前线程对volatile变量的修改,能即时的写回到共享主内存中,并被其他线程所见。
private boolean done; public synchronized boolean isDone(){ return done}; public synchronized boolean setDone(){ done = true};private volitile boolean done; public boolean isDone(){ return done}; public boolean setDone(){ done = true};
关键字threadLocal
主要作用:局部变量对当前线程可见,避免共享变量的风险。
public static final SimpleDateformat df = new SimpleDateformat("yyyy-MM-dd"); String dataStamp = df.format(new Date()); String dataStamp1 = df.format(new Date());//结果可能会混乱public Static final ThreadLocal<SimpleDateformat > df = new ThreadLocal<SimpleDateformat > {protected SimpleDateformat initualValue(){return new SimpleDateformat("yyyy-MM-dd");} }
线程安全集合
ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,ConcurrentLinkedQueue
Vector,Stack,Hashtable,Enumeration
常用的HashMap与ArrayList不是线程安全的,可用Collections.synchronized**变成线程安全的
List<E> synchArrayList = Collections.synchronizedList(new ArrayList<E>()); Map<K,V> synchHashMap = Collections.synchronizedMap(new HashMap<K,V>());
Thread类的常用方法
start();//启动线程
run();//线程实现逻辑,启动线程需要调用start,run方法单线程的
getId();//获得线程ID
getName();//获得线程名字
getPriority();//获得优先权
isAlive();//判断线程是否活动
isDaemon();//判断是否守护线程
getState();//获得线程状态
sleep(long mill);//休眠线程
join();//,同步主线程,等待线程结束
yield();//暂停当前线程,让其他线程先执行
interrupt();//中断线程
currentThread();//获得正在执行的线程对象
线程池ThreadPool
线程池是指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程。
带来的好处:
1.由于创建线程、销毁线程比线程执行更消耗资源。线程池避免了重复的创建线程、销毁线程所带来的消耗,提高了效率。
2.线程池减少了线程数量,可控制线程最大数。防止线程过多,导致阻塞。
3.线程池提供了很多属性,可以对线程进行的简单地管理,定时延时等。
ThreadPoolExecutor类
JDK中线程池的实现。构造方法最多有七个参数配置。
public ThreadPoolExecutor(int corePoolSize,//线程池最大核心线程数int maximumPoolSize,//线程池最大线程数long keepAliveTime,//非核心线程闲置超时时间 TimeUnit unit,//keepAliveTime的单位 BlockingQueue<Runnable> workQueue,//线程等待队列 ThreadFactory threadFactory,//工厂模式建立线程 RejectedExecutionHandler handler){...}//异常处理 threadPoolExecutor.execute(Runnable);//执行
ThreadPoolExecutor创建线程
1.线程数量未达到corePoolSize,新建核心线程
2.线程数量达到corePoolSize,进入等待队列workQueue
3.队列已满,新建非核心线程,执行任务
4.队列已满,maximumPoolSize也已达到,RejectedExecutionHandler进行抛错。
常用的线程池:
CachedThreadPool():可缓存线程池,作线程的创建数量几乎没有限制,可灵活回收空闲线程,使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); cachedThreadPool.execute(new Runnable() {public void run() {...} });
FixedThreadPool():定长的线程池,每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。但是线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); fixedThreadPool.execute(new Runnable() {public void run() {...}});
ScheduledThreadPool():定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool .execute(new Runnable() {public void run() {...}});
SingleThreadExecutor():单线程化的Executor,即只创建唯一的工作者线程来执行任务,单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor .execute(new Runnable() {public void run() {...}});
转载于:https://www.cnblogs.com/wqff-biubiu/p/8639607.html
多线程及Thread类、Runnable接口相关推荐
- Android开发之多线程编程Thread和Runnable使用
Android开发之多线程编程Thread和Runnable使用 Android可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:前者只要继承了Thread类同时覆写了 ...
- 多线程实现方式---实现Runnable接口
多线程实现方式---实现Runnable接口 多线程实现方式---实现Runnable接口 一个类如果需要具备多线程的能力,也可以通过实现java.lang.Runnable接口进行实现.按照Java ...
- java多线程(一)-Thread类和Runnable接口
public class Thread extends Object implements Runnable Thread通过实现Runnable实现多态关系. Java中实现多线程,最基本2种方式: ...
- Java多线程,Thread,Runnable,Callable Task,Future<Task>,CompletionService
一.Java多线程的方法 1. 继承 Thread 2. 实现 Runnable 3. 实现 Callable 可以有返回值 package com.test;import java.util.Arr ...
- 并发编程之多线程基础-Thread和Runnable的区别及联系(二)
上篇文章讲述了创建线程的常用方式 本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系 联系: ▶Thread类实现了Runable接口. ▶都需要重写里面Run方法. 区别: ...
- C++多线程:thread类创建线程的多种方式
文章目录 描述 函数成员简介 总结 描述 头文件 <thread> 声明方式:std::thread <obj> 简介 线程在构造关联的线程对象时立即开始执行,从提供给作为构造 ...
- PYTHON——多线程:Thread类与线程函数
Thread类与线程函数 可以使用Thread对象的join方法等待线程执行完毕:主线程(main()函数)中调用Thread对象的join方法,并且Thread对象的线程函数没有执行完毕,主线程会处 ...
- python多线程:Thread类的用法
我们要创建Thread对象,然后让他们运行,每个Thread对象代表一个线程,在每个线程中我们可以让程序处理不同的任务,这就是多线程编程. 创建Thread对象有两种方法: 1.直接创建Thread, ...
- Java多线程-继承Thread类,示例
继承Thread类,调用start方法启动线程. 示例, public class ThreadTest extends Thread {public ThreadTest(String name){ ...
- Java多线程和并发(三),Thread类和Runnable接口
目录 1.Thread和Runnable接口 三.Thread类和Runnable接口 1.Thread和Runnable接口 转载于:https://www.cnblogs.com/xzmxddx/ ...
最新文章
- 2022-2028年中国手机支付市场投资分析及前景预测报告
- Java中的Timer和Timer Task详解
- 简述http请求中的同步和异步
- application time for the banking industry
- el表达式动态取值中括号内两点_中考热点:旧瓶新酒,解题新策略分析之玩转动态型热点题型...
- POJ - 3683 Priest John's Busiest Day(2-SAT+路径打印)
- 计算机教育的需求,我国教育信息化市场需求分析
- 遗传算法求二元函数极值怎么编码_用遗传算法求复杂函数的极值点
- arm9260 linux编译,关于linux9260烧写软件和gdb调试器的使用
- 蓝牙强势整合UWB/wifi/zigbee
- 架构名词,涉及的技术
- CentOS6.x 下 LNMP环境搭建(二、安装 Nginx)
- 微软职位内部推荐-Software Engineer
- 拓端tecdat|R语言时间序列和ARIMA模型预测拖拉机销售的制造案例研究
- 开元酒店在中国的签约及在营酒店规模正式超过600家
- TCP中 滑动窗口RWND 和 拥塞窗口 CWND的区别
- 4x root 红米_小米红米Note4X获取root权限教程
- Android 全屏悬浮窗适配(悬浮窗沉浸式)
- windows 7 优化快速设置参考(实测好用)
- 【自动化运维新手村】Web框架序篇
热门文章
- 【2017级面向对象程序设计】作业二
- glibc的几个有用的处理二进制位的内置函数(转)
- text-align 属性,输入框数字向右靠
- JAVA环境变量的配置方法【希望可以帮助你】【个人实测没问题】
- Javascript获取地址参数
- 118 Python程序中的线程操作-守护线程
- 陌上花开(三维偏序)(cdq分治)
- python之路_保留原搜索页面条件
- gbdt 算法比随机森林容易_数据挖掘面试准备(1)|常见算法(logistic回归,随机森林,GBDT和xgboost)...
- docker compose启动服务超时重启记录