一、线程的简介
JAVA语言提供了并发机制,程序员可以在程序中执行多个线程,每个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程。
一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程。
一个线程则是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。
二、创建线程
2.1继承Thread类
从这个类中实例化的对象代表线程,启动一个新线程需要建立Thread实例
Thread类中常用的两个构造方法如下:
①public Thread():创建一个新的线程对象
②public Thread(String threadName):创建一个名为threadName的线程对象
继承Thread类创建一个新的线程的语法如下:
public class ThreadTest extends Thread{
}
完成线程真正功能的代码放在类的run()方法中,然后调用Thread类中的start()方法执行线程
public void run(){
}
※如果不调用start()方法,线程永远不会启动,在没有调用start()方法前,Thread对象只是一个实例,而不是一个真正的线程。
2.2实现Runnable接口
如果需要继承其他类(非Thread类),而且还要使当前类实现多线程,那么可以通过Runnable接口来实现。
实现Runnable接口的语法如下:
public class Thread extends Object implements Runnable{
}
※继承一个接口时,需要实现接口中的所有方法
实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联
Thread类中有两个构造方法,使用一下构造方法可以将Runnable实例与Thread实例相关联:
①public Thread(Runnable target)
②public Thread(Runnable target,String name)
※使用Runnable接口启动新的线程的步骤如下:
(1)建立Runnable对象
(2)使用参数为Runnable对象的构造方法创建Thread实例
(3)调用start()方法启动线程
首先需要编写一个实现Runnable接口的类,然后实例化该类的对象,这样就建立了Runnable对象;
接下来在类的构造方法中创建Thread实例;
最后使用该实例调用Thread类中的start()方法启动线程。
2.3线程的生命周期
线程具有生命周期,有7中状态:
出生:线程被创建时,在使用start()方法前线程都处于出生状态;
Thread t=new Thread;
就绪:调用start()方法后,线程处于就绪状态;
运行:线程得到系统资源后进入运行状态;
等待:当处于运行状态下的线程调用wait()方法时,该线程进入等待状态,此时调用notifyAll()方法可以将所有处于等待状态下的线程唤醒;
休眠:调用sleep()方法时,线程进入休眠状态;
阻塞:线程在运行状态下发出输入/输出请求,该线程进入阻塞状态,在等待输入/输出结束时,线程进入就绪状态,不能回到运行状态;
死亡:run()方法执行完毕时,线程进入死亡状态。
2.4操作线程的方法
一、线程的休眠sleep()
sleep()方法需要一个参数用于指定该线程休眠的时间,以毫秒为单位,通常在run()方法内的循环中被使用:
try{
Thread.sleep(2000);//使线程在2秒内不会进入就绪状态,醒来后进入就绪状态
}catch(InterruptedException e){
e.printStackTrace();
}
二、线程的加入join()
如果当前某程序为多程序程序,假如存在一个线程A,现在需要插入线程B,并要求线程B先执行完毕,再继续执行A,此时可以使用join()方法来完成。
例:创建两个线程分别负责进度条的滚动,在线程A的run()方法中使线程B的对象调用join()方法,而join()方法使当前运行线程暂停,直到调用join()方法的线程执行完毕后再执行,所以线程A等待线程B执行完毕后再开始执行。
三、线程的中断interrupt()
如果线程是因为使用了sleep()或wait()方法进入了就绪状态,可以使用interrupt()方法使线程离开run()方法,同时结束线程,但程序会抛出InterruptedException异常,用户在处理该异常时完成线程的中断业务处理,如,终止while循环
四、线程的礼让yield()
给当前正处于运行状态的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。
yield()方法使具有同样优先级的线程有进入可执行状态的机会,在当前线程放弃执行权时会再度回到就绪状态。
2.5线程的优先级
每个线程都具有各自的优先级,可以表明在程序中该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定首先使那个线程进入运行状态。
Thread.MIN_PRIORITY(常数1)、Thread.MAX_PRIORITY(常数10)、Thread.NORM_PRIORITY(常数5)
在默认情况下优先级都是Thread.NORM_PRIORITY,每个新线程都继承了父线程的优先级
2.6线程同步
一、线程同步机制
1、同步块
java中提供了同步机制,可以有效地防止资源冲突,同步机制使用synchronized关键字,使用该关键字包含的代码块称为同步块或临界区,语法如下:
synchronized(Object){
}
通常将共享资源的操作放置在synchronized定义的区域内,这样当其他线程获取到这个锁时,就必须等待锁被释放后才可以进入该区域;
Object为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为0和1.
一个线程运行到同步块时,先检查该对象的标志位,如果为0,表明此同步块内存在其他线程,这时当期线程处于就绪状态,直到处于同步块中的线程执行完同步块中的代码后,这时该对象的标识位设置为1,当期线程才能开始执行同步块中的代码并将Object对象的标识位设置为0,防止其他线程执行同步块中的代码。
2、同步方法
在方法面前用synchronized关键字修饰,语法如下:
synchronized void f(){
}
当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步方法执行完毕后才能被执行,必须将每个能访问共享资源的方式修饰为synchronized,否则会报错。