线程的使用
启动
thread.start();
1,启动线程 void start();
1,开辟新的执行路径(线程)
2,此时该线程才会与其他线程抢夺CPU执行权
注意:线程启动后会执行run方法中的代码
2,线程的休眠
static void sleep(毫秒) 注意:
1,线程休眠期间不会抢夺CPU执行权
2,使用类名调用方法,在那个线程中调用,就让那个线程休眠
练习:在子线程中进行10秒倒计时
3,获取当前线程
static Thread currentThread();
4,线程名称
获取线程名称 String getName() 设置线程名称
1,使用setName方法 线程对象.setName(线程名称);
2,在创建线程对象时传入线程名称 new Thread(线程任务,线程名称); 注意:在线程启动前设置
Thread thread1 = new Thread(send1,"窗口一");
5,线程的优先级
概念:线程抢夺到CPU执行权的概率(不能做到百分百)
注意: 1,取值范围1~10 2,在线程启动前设置
3,默认优先级为5
设置线程优先级 void setPriority(int newPriority)
获取优先级 int getPriority()
6,线程的礼让
概念:当线程获取到了CPU执行权后,又释放CPU执行权,然后从新抢夺
方法: static void yield()
7,线程的合并
概念:将多个线程合并为一个线程
方法: void join()
注意:
在线程2中使用线程1对象调用该方法,表示将线程1未完成的代码合并到线程2中,此时只要执行完线 程1中剩余的代码,才会继续执行线程2剩余的代码 一般不会自己合并自己
8,守护线程
设置线程为守护线程: void setDaemon(boolean on)
默认 true:为守护线程 flase:为前台线程,
注意:当一个进程中所有前台线程执行完毕后,进程将会结束
9,前台线程 默认创建的线程就是前台线程 注意: 主线程(main方法里面的线程)也是前台线程
10,线程关闭 注意:不要调用提供的关闭方法
线程关闭时机:当run方法中的代码执行完毕后,等待JVM回收
线程使用场景
在生活中同时做多个事情,那么在代码就应该用线程描述 案例: 购买火车票 假设: 四个窗口:四个线程 线程任务:买票,票没了就不买了 注意:四个窗口共享剩余票的数量
线程使用安全
原因:因为多个线程操作同一个数据导致的线程不安全
解决方法:保证同时只能有一个线程操作
Java如何保证同时只能使用一个线程操作:
使用synchronized的关键字
使用: 同步代码块 语法: synchronized(锁对象){ 要同步的代码 }
注意: 1,保证多个线程使用的锁对象是同一个对象
2,所有的类的对象都可以作为锁对象
同步方法
语法:使用synchronized修饰方法
访问权限修饰符 synchronized 返回值类型 方法名(形参列表){ 方法体 }
注意: 1,谁调用同步方法,谁就是锁对象
同步静态方法
语法:
使用synchronized修饰方法 访问权限修饰符 synchronized static 返回值类型 方法名(形参列表){ 方法体 }
注意: 1,锁对象是同步静态方法所属的类的类对象
死锁
目的:避免死锁
原因:多个线程互相持有对方所需的锁资源
如何避免死锁: 尽量不要在同步中使用同步 表现: 代码不会继续执行,程序也没有停
即不要使用两个synchronized
线程间通讯
注意: 线程间通讯的方法是Object提供的方法
方法:
休眠
wait():无限期休眠
wait(timeout): 有限期休眠 timeout:休眠时间,单位毫秒
wait(timeout,nanos):有限期休眠 timeout休眠时间,单位纳秒 因为精度太高了,所以不用
sleep与wait的区别:
sleep:
1,是Thread类提供的方法
2,是静态方法
3,休眠期间不会释放锁资源
4,在线程中都可以使用
5,使用线程对象或Thread类名调用
wait:
1,是Object类提供的方法
2,不是静态方法
3,休眠期间会释放锁资源
4,只能在同步代码中使用
5,只能使用当前所在的同步的锁对象调用
唤醒
notify():随机唤醒一个正在休眠的线程(参考注意点3)
notifyAll():唤醒所有正在休眠的线程(参考注意点3)
注意:
1,只能在同步代码中使用
2,只能使用当前所在的同步的锁对象调用
3,只能唤醒使用该对象使其休眠的线程
a锁锁了三线程a1,a2,a3 b锁锁了二线程b1,b2
a.notifyAll();只能唤醒a1,a2,a3
同一把锁
a.notify():随机在a1,a2,a3唤醒一个