多线程
程序是为完成特定的任务、用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象。
进程是程序的一次动态执行,或者是正在运行的一个程序。动态过程,有它自身的产生、存在、消亡
线程:是一个程序内部的一条执行路径,若一个程序执行过程中,在同一时间可以执行多个线程,就是支持多线程的
每个程序中都隐含一个主线程、main()方法
何时需要多线程:
程序需要同时执行两个或者多个任务
程序需要实现一些等待的任务,如:用户输入、文件的读写操作、网络操作、搜索
需要一些后台运行程序时候
线程的创建和启动
public class Sample {
public void method1(String str){
System.out.println(str);
}
public void method2(String str){
method1(str);
}
public static void main(String[] args) {
Sample s = new Sample();
s.method2("hello!");
}
}
多线程的创建和启动
java语言的jvm运行创建多个线程,它通过java.lang.Thread类来实现
Thread类的特性:
每个线程都是通过某个特定的Thread对象的run方法来完成操作的,经常把run方法的主体称为线程体,通过该Thread对象的start方法调用这个线程
构造方法:
Thread():创建新的Thread对象
Thread(String name)创建线程并指定实例名称
Thread(Runnable target):指定创建线程的目标对象,它实现了Runnable接口中的run方法
Thread(Runnable target, String name)创建新的Thread对象
创建线程的两种方式:
1、继承Thread类,重写类中的run方法,创建线程对象,调用start方法,启动线程
2、实现Runnable接口:重写接口中的run方法,通过带参构造创建对象,调用start方法,开启线程
继承方式和实现方式的区别和联系:
public class Thread extends Object implements Runnable{}
实现方法的好处:
1、避免了单继承的局限性
2、多个线程可以共享一个接口实现类的对象,非常合适多个相同线程线程来处理同一份资源
线程的调度:
线程的优先级:
线程的优先级控制
线程创建时候继承父线程的优先级
Thread类的有关方法:
线程让步:暂停当前正在执行的线程,把执行机会让给优先级更高或者相同的其它线程,若对列中没有优先级相同的线程,忽略此方法
当某个程序调用其他线程的join方法时候,调用线程将被阻塞,知道join方法线程执行完成(第优先级的方法也可以先执行)
使用多线程的优点:
只使用单个线程完成多个任务(调用多个方法),肯定比用多个线程来完成时间更短
多线程的优点:
1、提高应用程序的相应,对图形化界面更有意义,可以增强用户体验
2、提高计算机系统的cpu利用效率
3、改善程序结构,将既长又复杂的进程分为多个线程,独立运行,利于理解和修改
线程的分类:一种是守护线程、一种是用户线程(唯一的区别是jvm何时离开),守护线程是用来服务用户线程的,通过在start方法前调用thread.setDeamon(true)可以把一个用户线程变成一个守护线程
java垃圾回收就是一个典型的守护线程
若jvm都是守护线程,当前jvm将退出
线程的声明周期:jdk中用Tread.State枚举表示了线程的集中声明周期
要想实现多线程,必须在主线程中创建新的线程对象
新建:
就绪:新建的e线程经过start方法后,就进入了线程队列进行等待cpu时间片,此时已经具有了运行的条件
运行:就绪的线程被调度并获得处理器的资源时候,便进入运行状态,run方法中定义了线程的操作和功能
阻塞:在某些特殊情况下,被认为挂起或者执行输入输出操作的时候,让出cpu并临时终止自己的执行,进入阻塞状态
死亡:线程完成它的所有工作,或者被强制性的终止
线程同步:
多个线程执行的不确定性引起执行结果的不稳定性
多个线程对共享,会造成操作的不完整性,会破坏数据
synchronized的使用方式:
synchronized(对象){需要同步的代码}
synchronized可以放在方法声明中,表示整个方法为同步方法
public synchronized void show(String name){}
互斥锁:(保证共享数据的操作的完整性)
每个对象都对应一个可称为“互斥锁”的标记,这个标记用来保证在任意时刻,只有一个线程访问该对象
同步的局限性:导致程序的执行效率变低
同步方法(非静态)的锁为this
同步方法(静态)的锁为当前类本身
释放锁的e操作:
当前线程的同步方法、同步代码块执行结束
当前线程在同步代码块中、同步方法中遇到了break、return终止了该代码块的执行
当前线程在同步代码块中、同步方法出现了异常
当前线程在同步代码块中执行了对象的wait方法,当前线程暂停、并释放了锁
不会释放锁的操作:
在执行同步代码块中,程序调用Thread.sleep() Thread.yield()方法暂停当前线程的执行
线程执行同步代码块中,其他线程调用了该线程的suspend()方法将该线程挂起
应该尽量避免使用suspend()和resume()来控制线程
线程的死锁问题:
不同的线程都在分别占用对方需要的资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
解决办法:
专门的算法、原则
尽量减少同步资源的定义
线程通信:
wait() notify() notifyAll()
wait:令当前线程挂起并放弃cpu、同步资源、是别的线程可以访问并修改共享资源,而当前线程排队等待再次对资源的访问
notify:唤醒正在等待的线程(优先级最高者)
notifyAll:唤醒正在排队等待资源的所有线程结束等待
java.lang.Object提供的这三个方法只有在synchronized方法或代码块中 才能使用