packagecom.nike.erick.d02;publicclassDemo03{publicstaticvoidmain(String[] args){Thread firstThread =newThread(newRunnable(){@Overridepublicvoidrun(){int i =0;while(true){
i++;System.out.println("T1--->"+ i);}}});Thread secondThread =newThread(newRunnable(){@Overridepublicvoidrun(){int i =0;while(true){Thread.yield();// 可以放弃当前线程
i++;System.out.println(" T2--->"+ i);}}});
firstThread.setPriority(10);
firstThread.start();
secondThread.setPriority(1);
secondThread.start();}}
sleep应用
程序一直执行,浪费cpu资源
packagecom.dreamer.multithread.day02;publicclassDemo01{publicstaticvoidmain(String[] args){while(true){System.out.println("i am working");}}}
程序间歇性休眠,让出cpu资源, 避免空转
packagecom.dreamer.multithread.day02;importjava.util.concurrent.TimeUnit;publicclassDemo01{publicstaticvoidmain(String[] args)throwsInterruptedException{while(true){TimeUnit.SECONDS.sleep(1);System.out.println("i am working");}}}
3. Join
谁调用 join,就等谁的线程结束后再去运行当前线程
3.1. join()
等待当前线程执行完毕
public final void join() throws InterruptedException
单个线程
packagecom.dreamer.multithread.day02;importjava.util.concurrent.TimeUnit;publicclassDemo02{staticint number =0;publicstaticvoidmain(String[] args){Thread slaveThread =newThread("t1"){@Overridepublicvoidrun(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedException e){
e.printStackTrace();}
number =10;}};
slaveThread.start();// t1线程调用join,t1线程就是插队执行try{
slaveThread.join();}catch(InterruptedException e){
e.printStackTrace();}System.out.println("number: "+ number);}}
多个线程
packagecom.dreamer.multithread.day02;importjava.util.concurrent.TimeUnit;publicclassDemo03{publicstaticvoidmain(String[] args)throwsInterruptedException{Thread firstThread =newThread(()->{try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){
e.printStackTrace();}});Thread secondThread =newThread(()->{try{TimeUnit.SECONDS.sleep(2);}catch(InterruptedException e){
e.printStackTrace();}});
firstThread.start();
secondThread.start();/**
* 1. 两个线程同时插队,以相同优先级执行
* 2. 所以一共等待时间为2s
*/long begin =System.currentTimeMillis();
firstThread.join();
secondThread.join();long end =System.currentTimeMillis();System.out.println("total time consuming: "+(end - begin));}}
3.2 join(long millis)
有时效的等待:最多等待多少ms, 0 代表永远执行完毕
假如线程join的等待时间超过了实际执行时间,执行完后就可以不用继续等了
public final synchronized void join(long millis) throws InterruptedException
packagecom.dreamer.multithread.day02;importjava.util.concurrent.TimeUnit;publicclassDemo02{staticint number =0;publicstaticvoidmain(String[] args){Thread slaveThread =newThread("t1"){@Overridepublicvoidrun(){try{TimeUnit.SECONDS.sleep(4);}catch(InterruptedException e){
e.printStackTrace();}
number =10;}};
slaveThread.start();// t1线程调用join,t1最多插队1秒,然后就继续执行当前线程try{
slaveThread.join(1000);}catch(InterruptedException e){
e.printStackTrace();}// 0System.out.println("number: "+ number);}}
3.3 应用
同步等待其他线程的结果调用
4. interrupt
# Thread 类# 1. 打断线程,谁调用打断谁
public void interrupt()# 2. 判断线程是否被打断 : 默认值为true# 不会清除打断标记
public boolean isInterrupted()# 会将打断标记置为false
public static boolean interrupted()
packagecom.nike.erick.d02;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.locks.LockSupport;publicclassDemo08{publicstaticvoidmain(String[] args)throwsInterruptedException{Thread thread =newThread(newRunnable(){@Overridepublicvoidrun(){System.out.println("slave thread running");LockSupport.park();System.out.println("after first park...");// 获取当前线程的打断标记,同时将打断标记清除,即为 falseSystem.out.println("打断标记:"+Thread.interrupted());LockSupport.park();// 再次parkSystem.out.println("after second park...");}});
thread.start();TimeUnit.SECONDS.sleep(1);
thread.interrupt();TimeUnit.SECONDS.sleep(3);
thread.interrupt();}}
5. 其他方法
### 1. 成员方法# 1. 名字
public final synchronized void setName(String name)
public final String getName()# 2. 优先级:最小为1,最大为10,默认为5# 只是一个cpu执行目标线程的顺序 建议设置,任务调度器可以忽略它进行分配资源
public final void setPriority(int newPriority)
public final int getPriority()# 3. 线程id: 13
public long getId()# 4. 是否存活
public final native boolean isAlive()# 5. 是否后台线程
public final boolean isDaemon()# 6. 获取线程的状态
public State getState()
NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED
### 2. 静态方法# 1. 获取当前线程
public static native Thread currentThread()## 3. 过时方法
- stop:停止线程运行
- suspend: 让线程暂停使用
- resume: 恢复线程运行
- 不推荐理由: 这三种方法,都可能造成死锁问题
packagecom.nike.erick.d03;publicclassDemo03{privatestaticRoom room =newRoom();publicstaticvoidmain(String[] args)throwsInterruptedException{Thread firstThread =newThread(newRunnable(){@Overridepublicvoidrun(){for(int i =0; i <1000; i++){
room.decrement();}}});Thread secondThread =newThread(newRunnable(){@Overridepublicvoidrun(){for(int i =0; i <1000; i++){
room.increment();}}});
firstThread.start();
secondThread.start();
firstThread.join();
secondThread.join();System.out.println("result:"+ room.getValue());}}classRoom{privateint counter;// 锁对象一般用当前对象publicvoidincrement(){synchronized(this){
counter++;}}publicvoiddecrement(){synchronized(this){
counter--;}}publicintgetValue(){synchronized(this){return counter;}}}
2.2 同步方法
成员方法
同步成员方法和同步代码块效果一样,必须保证同步代码块的锁对象是this对象
可能锁粒度不太一样
同步方法的锁对象是this,即当前对象
@DataclassCalculator{privateint number;publicvoidincr(){synchronized(this){for(int i =0; i <10000; i++){
number++;}}}// 同步方法publicsynchronizedvoiddecr(){for(int i =0; i <10000; i++){
number--;}}}
静态成员方法
锁对象:锁用的是类的字节码对象: Calculator.class
@DataclassCalculator{privatestaticint number;publicintgetNumber(){return number;}publicstaticvoidincr(){for(int i =0; i <10000; i++){synchronized(Calculator.class){
number++;}}}publicstaticsynchronizedvoiddecr(){for(int i =0; i <10000; i++){
number--;}}}
// 安全packagecom.nike.erick.d01;importjava.util.ArrayList;importjava.util.List;publicclassDemo05{publicstaticvoidmain(String[] args){ArrayList<String> list =newArrayList<>();SafeCounter safeCounter =newSafeCounter();
safeCounter.operation(list);System.out.println(list);}}classSafeCounter{publicvoidoperation(List<String> list){for(int i =0; i <10000; i++){addElement(list);deleteElement(list);}}publicvoidaddElement(List<String> list){
list.add("HELLO");}publicvoiddeleteElement(List<String> list){
list.remove(0);// 移除元素}}
// 不安全packagecom.nike.erick.d01;importjava.util.ArrayList;importjava.util.List;publicclassDemo05{publicstaticvoidmain(String[] args){ArrayList<String> list =newArrayList<>();UnsafeCounter unsafeCounter =newUnsafeCounter();
unsafeCounter.operation(list);System.out.println(list);}}classSafeCounter{publicvoidoperation(List<String> list){for(int i =0; i <10000; i++){addElement(list);deleteElement(list);}}publicvoidaddElement(List<String> list){
list.add("HELLO");}publicvoiddeleteElement(List<String> list){
list.remove(0);// 移除元素}}classUnsafeCounterextendsSafeCounter{@OverridepublicvoiddeleteElement(List<String> list){/*开启了新的线程来改变*/// index out of bound// 相当于把删除的操作延迟或提前了newThread(()-> list.remove(0)).start();}}