十二章 JAVA多线程
1.多线程
程序:程序是类、接口和对象的有序集合,程序是静态的。
进程:我们把系统执行一次程序的过程称为进程。
线程:操作系统将一个进程分为多个并行执行的线程,也就是说,经一个进程的载体分为多个独立的程序片段,这些程序片段可以并行执行。每个程序片段执行的过程就是线程的创建、运行和销毁的过程。线城是比进程更小的运行单位。
线程的生命周期:同进程一样,一个线程也有从创建、运行到消亡的过程,线程的这一过程称之为线程的生命周期。
线程状态转移:

2.创建线程
创建线程的方法有两种:一种是定义一个类实现Runable接口,然后以该类为模版创建一个目标对象,再以目标对象为参数构造一个线程;另一种是扩展Thread类,以定义自己的线程类,再以自定义的线程类为模板创建线程对象
①Runable接口与Thread类
程序执行时,首先启动主线程,即首先执行main()方法,运行一个线程就是执行run()方法,run()在Runable接口中声明
Runable接口放在java.lang包中,该接口声明了一个run()方法,我们把一个线程要执行的操作写在run()方法中
Thread类:它实现了Runable接口,并将run()方法实现为空方法,同时还拥有许多用于创建和控制线程的方法
声明方法:public class Thread extends Object implements Runable
②扩展Thread类创建线程
要创建一个自定义线程类,首先应该扩展Thread类,覆盖其中的run()方法。由于运行线程就是执行run()方法,因此将用户希望执行的操作写在run()方法中。
③实现Runable接口创建线程
步骤:首先定义一个目标类,该目标实现Runable接口,即对接口中的run()方法进行重写,把用户希望执行的操作写在run()方法中,然后以目标对象为参数,用构造方法Thread(Runable target)创建一个线程只有Thread类创建的线程才能访问和控制线程
3.线程组
线程组把多个线程组织在一起进行统一管理。通常使用java.lang包中的ThreadGroup类来创建线程组,线程组也是一个对象。
线程组中也可以加入线程或线程组。线程组之间构成树状继承关系。最高层的线程组是main线程组。
使用线程组的步骤:
ThreadGroup g=new ThreadGroup(“线程组名字”); //创建线程组
Thread t=new ThreadClass(g, “ThreadsName”); //将线程加入到线程组中
int sum=g.activeCount(); //获得线程组中活动线程的数目(活动线程是指处于就绪状态,阻塞状态,运行状态之一的线程)
4.线程调度与控制
①线程调度:同一线程在就绪队列中等待CPU的可能有多个线程,系统会给每个线程分配一个优先级。任务紧急、重要的线程分配的优先级较高,相反则较低。
线程调度管理器是依据某个算法来调度线程的,其规定高优先级优先调度,而同等优先级的线程调度遵循“先到先服务”的原则。
②线程的优先级:线程的优先级用数字1~10表示,1表示优先级最低,10表示优先级最高,默认情况下系统给线程分配的优先级是5
public final int getPriority(): 获得线程的优先级
public final void setPrioritu(): 设定线程的优先级
③控制线程状态转移
线程睡眠sleep():
public static void sleep(long millis) throws InterruptedException
线程执行该方法时,线程停止执行millis毫秒,线程由运行状态进入阻塞状态;睡眠时间过后,线程再进入就绪状态。
暂停线程(yield()):
public static void yield()
线程执行该方法时,县城性运行状态进入就绪状态,此时系统选择其他同优先级线程执行,若无其他同优先级线程,则从就绪状态列中选取本线程继续执行。
yield()方法的优点是:当有任务要处理时,系统不会让CPU闲置
连接线程(join()):
线程执行该方法时,线程转入阻塞状态。当阻塞原因消除后就进入就绪状态。调用该方法的线程运行结束后,再继续直行进入就绪状态的本线程。
调用方式格式:
public final void join() throws InterruptedException
public final void join(long millis) throws InterruptedException
public final void join(long millis,int nanos) throws InterruptedException
等待调用该方法的线程结束,或者最多等待millis毫秒+nanos纳秒后,再继续执行本线程。
设置中断、测试中断和清除中断(interrupt())
public void interrupt() 为线程设置中断标志并没有中断线程运行,一个线程在被设置了中断标记之后仍可以运行
public boolean isInterrupted() 检测线程是否已设置中断标记,若设置了中断标记则返回true
public static boolean interrupted() 测试线程是否被中断,若线程已被中断,则清除中断标记,并返回值true
5.线程同步
线程需要同步执行主要应用在两个方面:
共享数据的多个线程需要实现互斥;收发数据的多个线程需要协调执行。
①实现线程互斥的机制
在Java中使用关键字synchronized实现多个线程对共享数据的互斥操作,即在任何时候只能有一个线程执行一段代码或一个方法。
关键字synchronized有两种用法:锁定一段代码或锁定一个方法
synchronized可以锁定一段代码,这段代码称为临界区。线程要执行这段代码,则必须获得资源的所有权。
第一个线程执行完临界区后自动释放了锁,此时第二个线程就可以获得对象的锁,并进去临界区执行,这样就实现了多个线程对同一个对象的“互斥”作用。该对象称为“同步对象”。
用关键字synchronized声明一种方法后,在同一个时刻只能有一个线程可以执行该方法。这种方法称为互斥方法。
②线程互斥实现数据共享
③线程协调实现的机制
如果多个同时运行的线程需要传送数据,则必须让多个线程按某个规则操作数据,即保证操作数据的线程步调一致,这样才能保证发送的数据被正确地接受到。
设置互斥目标:
要使发送和接收数据的线程步调一致,就应该为被操作的数据状态设置互斥标志,当互斥标志满足某个值时,对应的线程才能对数据进行操作。
实现线程协调:
为了实现线程执行的步调,就要用到java.lang.Object类提供的wait()、notify()和notifyAll()方法
④线程协调实现数据正确收发

浙公网安备 33010602011771号