JAVA多线程
一:概念:
5:守护线程:高尚的骑士守护圣洁的公主,公主不幸被魔龙掳走,在飞的过程中,公主从爪子缝隙中滑出,在万米高空中摔落致死。骑士保住公主痛哭,自己也没有了活下去的必要,拔剑自刎。这就是守护线程。
1:进程:正在执行的程序
2:线程:包含在进程中的执行线索
打开任务管理器,会看到进程一栏,是电脑正在运行的所有程序。也许会想:明明只打开了一 个程序,为什么会有一堆进程?这里的进程包括前台线程和后台线程。
一个进程包含N个线程。好比QQ上和多个人聊天。
3:单线程:必须顺序执行,前面的不执行完毕,后续的代码没有机会执行。
4:多线程:同时执行多段代码,多个代码块之间互不影响。(并发)
6:前台线程:正常启动的线程。
当一个进程中,还有一个前台线程,整个进程不会结束;当正在运行的线程都是守护线程时,JAVA虚拟机退出。
线程启动前,调用setDaemon(true);将线程标记为守护线程。
出征前,战士被国王授予勋章,成为公主的守护骑士。
7:优先级:最高优先级 10;最低优先级 1;默认优先级 5
优先级高的,只是有更多的机会被cpu执行,并不一定会在优先级低的线程前执行完毕。
方法——get/setPriority()
二:线程的创建方式
1:继承Thread类
步骤:
将类声明为Thread的子类
重写Thread类的run方法
创建线程的对象
通过start()方法启动线程
注意点:
①多个线程之间没有优先级,运行的顺序是无序的,随机的。
②不要手动调用run()方法
③同一个线程对象,只能调用start()方法开启一次,如果调用了多次start方法,线程只会调用一次。
④Thread.currentThread()获取当前的线程对象。getName()获取当前线程的名字。
2:实现Runnable接口
步骤:
实现Runnable接口
重写run()方法
创建实现类的对象
创建Thread类的对象
通过Thread类start()方法启动线程
这里变量用static修饰,是为了让变量归类所有,变成共享资源。所有线程一起用这40张票。
实现Runnbale接口和继承Thread类比较
1:实现Runnbale接口能够更好的体现资源的共享,把线程同程序代码、数据有效的分离(耦合性)
2:可以避免java单继承带来的局限性
三:线程的生命周期
1:新建——创建线程类的对象
2:就绪——调用start方法进入就绪状态,没有立即执行run方法
3:运行——开始执行
【4】阻塞——由于某些原因,导致线程被挂起。结束后进入就绪。
5:死亡——线程执行完毕
①run方法执行完毕,正常结束
②被其他线程杀死,或者调用了stop方法
灵魂画师上线
四:死锁
1:线程不安全前提:
①必须多个线程共享一个资源
②代码不具有原子性,同一段代码被多个线程执行
2:保证线程的安全性方法:synchroized
①使用同步代码块
②使用同步方法
③使用Lock类(jdk1.5以上)
步骤:
1:创建锁对象 private Lock lock = new ReentrantLock();
2:上锁 lock.lock()
3:释放锁 lock.unlock()
线程安全的同时,代码的运行效率会低。
(左边线程安全,右边执行效率高)
StringBuffer和StringBuilder
HashTable和HashMap
3:死锁
不恰当的应用synchronized来管理同步,并且循环依赖多个锁对象,造成程序被挂起,成为死锁。
举个栗子
创建两个Object类,重写带两个参数的构造方法。给一个Object类上锁,在锁里面再加一把锁,给另一个Object类上锁。
创建两个对象,参数顺序不同。第一个线程启动时,s1(或s2,无序)被挂起,CPU调用另一个线程,s2被挂起,这时CPU再次调用另一个线程,但是两个线程都被挂起,互不相让(也可能互相谦让),陷入僵局,造成死锁。
(和女朋友出去吃饭,钱只够买一个牛排,端上来时,你说:你先吃。女朋友:你先吃。牛排凉了,死锁了)
最后一个重点就是线程通信,wait()和notify()。一个消费者生产者模式,就是生产一个,消费一个,通信好,有默契,心有灵犀。背下例子就行。(好长,不好背/(ㄒoㄒ)/)
线程告一段落。
下回分解:集合框架