多线程
一、线程简介
同时进行,这种思想放在Java中被称为并发,而将并发完成的每件事情成为线程。系统可以分配给每个进程一段有限的使用CPU的时间(也可以称为CPU时间片),CPU在这段时间执行某个进程,然后下一时间片又跳至另一个进程中去执行,由于CPU转换较快,所以使得每个进程都好像同时执行一样。
一个线程则是进程中的执行流程,一个进程可以同时包含多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多的并发执行的线程。
二、实现多线程的两种方式
在java中提供两种方式实现线程,分别为继承java.lang.Thread和实现java.lang.Runnable接口。
完成线程真正功能的代码放在类的run()方法中,需要在主方法中启动线程,启动线程的方法为start()
2、实现Runnable接口
如果需要继承其他类(非Thread类),而且还要使当前类实现多线程,那么就可以通过Runnable类来实现。
注意:启动一个新线程,不是直接调用Thread子类对象的run()方法,而是调用Thread子类的start()方法,Thread类的start()方法产生一个新的线程,该线程运行Thread子类的run()方法。
三、线程的生命周期
线程具有生命周期,分别为出生状态、就绪状态、运行状态、等待状态、休眠状态、堵塞状态和死亡状态出生状态就是线程被创建时处于的状态,在用户使用该线程实例调用start()方法之前都是出于出生状态,当用户调用了start()方法之后,线程就处于就绪状态(又被称为可执行状态)当线程得到系统资源后就进入运行状态。
总结出使线程处于就绪状态有几种方法:
调用sleep()方法
调用wait()方法
等待输入输出完成。
当线程处于就绪状态后,可以使用以下几种方法使线程再次进入运行状态。
线程调用notify()方法
线程调用notifyAll()方法
线程调用interrupt()方法
线程的休眠时间结束
输入/输出结束。
四、操作线程的方法
1、线程的休眠
Sleep()方法执行有可能抛出InterruptedException异常,所以将sleep()方法的调用放在try{}catch(){}块中,sleep()方法醒来后进入就绪状态。
2、线程的加入
当某个线程使用join()方法加入另一个线程时,另一个线程会等待该线程执行完毕后再继续执行。
3、线程的中断
使用interrupyed()方法,同时程序抛出interruptedException异常,在异常处理时结束while()循环。在项目中经常在这里执行关闭数据库连接和Socket连接等操作。
4、线程的礼让
Thread提供了一种礼让方法,使用yield()方法表示,它只是给当前正处于运行状态下的线程一个提醒,告知它可以将资源礼让给其他线程,但这仅仅是一种暗示,没有任何一种机制会保证当前线程会将资源礼让给其他线程。
对于支持多任务的操作系统来说,不需要使用yield()方法,因为操作系统会为线程自动分配CPU时间片来执行。
五、线程的优先级
线程的优先级都在常量1~常量10之间,每个新产生的线程都继承了父线程的优先级。
六、线程同步
在单线程中,每次只能做一件事情,后面的事情需要等待前面的事情完成后才可以进行,但是如果使用多线程,就会发生两个线程抢占资源的问题,所以在多线程中需要防止这些资源访问的冲突,Java提供了线程同步的机制来防止资源访问的冲突。
1、线程安全
2、线程同步机制
同步块:在Java中提供了同步机制,可以有效地防止资源冲突。同步机制使用synchronized关键字。
可以看出,打印到最后票数没有出现负数,这是因为将资源放置在了同步块中,这个同步块也被称临界点,它使用synchronized关键字建立,其语法如下:
Synchronized(Object){
}
通常将共享资源放在synchronized定义的区域块内,Object为任意对象,每个对象都存在一个标志位,并具有两个值,分别为0和1,如为0状态,表示此同步块存在其他线程在运行,直到处于同步块中的线程执行完同步块中的代码为止。
同步方法:同步方法就是在方法前面加上synchronized关键字
Synchronized void f(){}
当某个对象调用了同步方法,该对象上其它同步方法必须等待该同步方法执行完毕后才能被执行,必须将每个能共享资源的方法修饰为synchronized,否则会出错。
public synchronized void doit(){
if(num>0){
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("ticket"+--numm);
}
}
public void run(){
while(true){
doit();
}
}
将共享资源的操作放置在同步方法中,运行结果与使用同步块的结果一样。