概念
注: main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集(gc )线程。
线程的创建
第一种:继承Thread类,重写run方法(其底层也是实现了Ruunable接口)
第二种:实现Runnable接口,重写run方法(启动线程时要把对象丢进Thread对象中)
两种方式的总结:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
第三种:实现Callable接口(了解)
线程属性
①线程ID,标识线程
②线程名字 ③线程优先级(1-10),优先级越高越优先执行,但并不成正比关系
④线程状态,NEW RUNNALBE BLOCKED WAITING TERMINATED
⑤线程类别,ture标识守护线程(后台记录操作日志,监控内存,垃圾回收),false标识用户线程。虚拟机必须保证用户线程的执行完毕,不用等待守护线程执行
线程状态
线程休眠sleep():
①参数为阻塞线程的毫秒数
②阻塞时间到了之后线程进入就绪状态
③每个对象都有一把锁,sleep不会释放锁
等待线程停止join():
①相当于插队,在主线程中是子线程join(),即主线程等待子线程执行完毕再执行
线程礼让yield():
①礼让的意思是停止cpu对该进程的执行,即从运行状态变成就绪状态
②礼让不一定成功,得看cpu的调度
线程停止:
①使其自动运行完然后停止
②可以设置一个标志位flag来停止线程
③不要使用stop()和destory()等过时或者JDK不建议的方法去停止线程
线程同步(并发)
package Algorithm.SYN;public class UnsafeThread {public static void main(String[] args) {Buytciket buytciket = new Buytciket();new Thread(buytciket,"1号").start();new Thread(buytciket,"2号").start();new Thread(buytciket,"3号").start();}}class Buytciket implements Runnable{//定义总数量private int TicketNum = 10;boolean flag = true;@Overridepublic void run() {//买票while (flag){try {buy();} catch (InterruptedException e) {e.printStackTrace();}}}private void buy() throws InterruptedException {//判断是否有票if(TicketNum <= 0){flag = false;return;}//模拟延时Thread.sleep(100);//买票System.out.println(Thread.currentThread().getName()+"买到了第"+TicketNum--+"票");}
}
可见出现了线程的并发问题。
锁机制(synchronized):
synchronized锁又可以分为synchronized方法和synchronized块:其默认锁的是this,即对象本身。synchronized块锁的是变化的量(对象)。
//synchronized同步方法private synchronized void buy() throws InterruptedException {//判断是否有票if(TicketNum <= 0){flag = false;return;}//买票System.out.println(Thread.currentThread().getName()+"买到了第"+TicketNum--+"票");}
拓展:JUC包下的安全集合CopyOnWriteArrayList,可以实现线程集合安全
死锁
private void mu() throws InterruptedException {if(choice == 0){//获得口红synchronized (lipstick){System.out.println(this.name+"获得口红");Thread.sleep(1000);synchronized (m){System.out.println(this.name+"获得镜子");}}}else{//获得口红synchronized (m){System.out.println(this.name+"获得镜子");Thread.sleep(2000);synchronized (lipstick){System.out.println(this.name+"获得口红");}}}
发生死锁!!进程全部阻塞
private void mu() throws InterruptedException {if(choice == 0){//获得口红synchronized (lipstick){System.out.println(this.name+"获得口红");Thread.sleep(1000);}synchronized (m){System.out.println(this.name+"获得镜子");}}else{//获得口红synchronized (m){System.out.println(this.name+"获得镜子");Thread.sleep(2000);}synchronized (lipstick){System.out.println(this.name+"获得口红");}}
产生死锁的条件:
Lock锁(显式)
两种锁的对比:
线程池
public class pool {public static void main(String[] args) {//创建线程池ExecutorService service = Executors.newFixedThreadPool(10);//线程池大小//执行service.execute(new my());service.execute(new my());service.execute(new my());service.execute(new my());//关闭连接service.shutdown();}
}class my implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}
}