多线程就是在一个应用程序中可以有多个线程任务执行。程序中同时需要执行多个任务时,就需要多线程。
(2)多线程的优缺点 优点:提高程序速度;
提高了cpu的利用率;
改善程序结构。
缺点:多线程程对内存消耗增高;
多线程切换执行,对cpu的要求也提高了(这两个缺点可以通过升级硬件设备解决);
多个线程访问同一个共享资源,会出现线程安全问题 出现线程安全问题。
单一的多线程不会出现线程安全问题 ,每个线程都在做自己的事情。
(3)线程并行与并发 线程并行执行: 多个人同时做不同的事情,互不干扰。
线程并发执行: 在一个时间段内一此执行某件事情。
解决线程安全问题就要给程序加锁,
(1)synchronized synchronized关键字
synchronized可以修饰代码块
synchronized(同步锁对象){ }
synchronized修饰方法时:
如果是非静态的方法,那么锁对象是this ;如果是静态方法,那么锁对象是类的Class对象(一个类只有一个Class对象)。
synchronized是靠底层指令控制实现。
synchronized可以修饰代码块,修饰方法,注意锁的对象(锁对象可能会变)。
synchronized加锁方式是隐式的,进入到同步代码块时,自动获取锁, 同步代码块执行完成后,自动释放锁。
(2) Lock接口Lock锁是靠java代码来控制,ReentrantLock类实现了Lock接口,可以来控制与synchronized相同的功能.。但是两者的实现细节完全不同的,Lock加锁只能对某段代码加锁,而且是显示的加锁和释放锁。
3.死锁出现原因:不正确的加锁方式可能会导致死锁问题。就是不同的线程分别占用对方需要的同步资源不放弃。
后果:出现死锁后,程序不会报错,只是等待.。
解决方式:锁的嵌套时容易发生死锁现象, 加锁时,考虑清楚锁的顺序,尽量减少嵌套使用。
4.线程通信 (1)线程通信线程通信就是多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作。就是多个线程在操作同一份数据时,避免对同一共享变量的争夺。多个线程之间相互牵制,制约运行。
(2)方法 wait() 让线程等待,调用wait()方法后线程进入到阻塞状态,必须通过另一个线程唤醒
notify() 唤醒等待中的线程
notifyAll() 唤醒等待中的所有线程
这3个方法必须在同步代码块中执行.
sleep()和 wait()
相同点: 都可以让线程进入到阻塞状态。
不同点: sleep() 是Thread类中方法,不会释放锁,休眠时间到了后,会自动进入到就绪状态;
wait() 是Object类中方法,wait()是可以释放锁的,wait()后的线程,需要使用notify()或者notifyAll()唤醒