一、并发和并行
并发:两个或多个事件在同一时间段内发生(交替执行)
并行:两个或多个事件在同一时刻发生(同时执行)
二、线程和进程
进程:
1)一个程序至少有一个进程
线程:
1)一个进程可以包含多个线程
2)线程是进程中一个执行单元,负责当前进程中程序的执行。
3)多线程程序并不能提高程序的运行速度,但是能够提高程序运行的效率,让CPU的使用率更高。
线程调度
1.分时调度
所有线程轮流使用CPU的使用权,平均分配每个线程占用的CPU的时间。
2.抢占式调度
优先让优先级高的线程使用CPU,如果线程的优先级相同,会随机选择
一个线程。Java使用的是抢占式调度。
3.主线程和单线程
主线程:执行主方法(main)的线程。
单线程程序:Java程序中只有一个线程,执行从main方法开始,从上到下依次执行。
一、创建多线程的方法
单继承多实现
1.继承Thread类并重写run()方法
调用start()方法启动线程
2.实现Runnable接口并且重写run()方法
好处
1)避免了单继承。一个类只能继承一个线程类
3. 匿名内部类方式创建线程
简化代码
解决线程安全问题
1.同步代码块
同步中的线程没有执行完不会释放锁,同步外的线程没有锁就进不去同步中
synchronized(锁对象){
线程安全问题的代码
}
1)代码块中的锁对象,可以使用任意的对象
2)多个线程使用的锁对象必须是同一个
3)锁对象的作用:把同步代码块锁住,只让一个线程在代码块中执行
2.同步方法
解决线程安全问题的第二种方法:同步方法
1)把访问了共享数据的代码抽取出来,放到一个方法中
2)在方法上添加synchronized修饰符
3)定义方法的格式
修饰符 synchronized 返回值类型 方法名(参数列表){
线程安全问题的代码
}
4)同步方法也会把方法内容的代码锁住,只让一个线程执行。
5)同步方法的锁对象是谁?就是类对象,也就是this
静态的同步方法
1)锁对象是谁?
不能是this,this是创建对象之后产生的,静态方法优先于对象,静态方法的锁对象是本类的class属性。
3.锁机制
java.util.concurrent.locks.lock机制
提供了更广泛的锁定操作,比同步代码块和同步方法更强大。
1)在成员位置创建一个Reentrantlock对象
2)在可能出现安全问题的代码前调用lock接口中的方法lock获取锁
3)在可能出现安全问题的代码后调用lock接口中的方法unlock释放锁
1、New(新建)
2、Runnable(可运行)
3、Blocked(被阻塞)
4、Waiting(等待)
5、Timed waiting(计时等待)
6、Terminated(被终止)
以下内容仅供参考
一、新建状态
创建线程的三种方式
1. 继承Thread类并重写run()方法
2. 实现Runnable接口并且重写run()方法
3. 匿名内部类方式创建线程
程序还没有开始运行线程中的代码
二、就绪状态
1. 一个新创建的线程并不自动运行,要执行线程,必须调用线程的start()方法。
当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。
2. 处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。
三、运行状态
当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.
四、阻塞状态
所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。
五、死亡状态
有两个原因会导致线程死亡:
1) run方法正常退出而自然死亡,
2) 一个未捕获的异常终止了run方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.
七、yield和sleep和wait
1.yield方法
(1)不会释放锁,让线程进入就绪状态.
(2)public static native void yield();
这是一个静态方法,一旦执行,它会让当前线程让出CPU,但是,需要注意的是,让出的CPU并不是代表当前线程不再运行了,如果在下一次竞争中,又获得了CPU时间片当前线程依然会继续运行。另外,让出的时间片只会分配给当前线程相同优先级的线程。
(3)如果一个线程实例A执行了threadB.join(),其含义是:当前线程A会等待threadB线程终止后threadA才会继续执行。
2.sleep方法
(1).它会让出cpu的使用权不会释放掉对象锁,sleep()方法可以在任何地方种使用
(2).sleep结束以后,线程进入就绪状态,而不是运行状态
(3).sleep()方法在休眠时间达到后如果再次获得CPU时间片就会继续执行。
(4)sleep()方法是Thread的静态方法,
3.wait方法
(1)wait()方法会释放占有的对象锁,如果调用的是不带时间参数的wait()则需要notify()或notifyAll()这两个方法来唤醒它然后进入锁池状态。进入锁池状态以后继续参与锁的竞争。
(2)wait是Object实例方法
(3)wait()方法必须要在同步方法或者同步块中调用,也就是必须已经获得对象锁
(4)一个线程如果的调用了带时间参数的wait(long milli)方法进入了定时等待状态,那么只要时间一到就会进入锁池状态,并不需要notify()或notifyAll()方法来唤醒它。