多线程

线程的使用方法 :

1.创建Thread类或者其子类,重写run方法,该run()方法是线程执行体。

2.创建一个Runnable类(更多使用)并重写该接口的run()方法,该run()方法同样是线程执行体。

package com.binbin.thread; /** * 〈thread〉 * * @author binbinarvin * @create 2019-01-25 */ class MyThread extends Thread{ public MyThread(String nameOne){super(nameOne);} public void run(){ System.out.println("mt线程正在执行"); int x = 0; while(x<10){ System.out.println(x+"=="); x++; } } } public class ThreadTest { public static void main(String[] args){ System.out.println("主线程1"); MyThread mt1 = new MyThread("one"); MyThread mt2 = new MyThread("two"); mt1.start(); //执行启动线程,一个线程只能启动一个,不能多次 mt2.start(); //三个线程运行,一个main一个mt1,一个mt2 System.out.println("主线程2"); //先输出主线程中每次顺序都不一样,这是因为随机获取CPU使用权 } }

 

package com.com.binbin.runnable; /** * 〈Runnable〉 * @author binbinarvin * @create 2019-01-25 */ class PrintRun implements Runnable{ int i = 1; @Override public void run() { while(i<10){ System.out.println(Thread.currentThread().getName()+"yunxing"+(i++)); } System.out.println(Thread.currentThread().getName()+"正在运行"); } } public class TestRunnable { //Java不支持多继承 //不打算重写Thread类的其他方法 //所以使用Runnable借口,它更广泛 public static void main(String[] args){ //三步进行Runnable的线程 也可以直接写成new Thread(new Producer(PrintRun)).start(); PrintRun r1 = new PrintRun(); Thread t1 = new Thread(r1); t1.start(); Thread t2 = new Thread(r1); t2.start(); //T1和T2共享一个线程,适用于线程比较大的情况 //如果有多个线程,那么他的执行方法和Thread一样,随机性 } }

 

 

 

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就     绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

 

 

package com.com.binbin.runnable; /** * sleep & join * @author binbinarvin * @create 2019-01-25 */ class PrintRun implements Runnable{ int i = 1; @Override public void run() { while(i<15){ System.out.println(Thread.currentThread().getName()+"运行"+(i++)); //Thread.currentThread().getName()得到当前线程名字 /** * try{ * Thread.sleep(1000);//隔一秒打印,中间休眠1000毫秒, * //这边使用sleep方法使用,如果有两个线程共同执行,那么很可能会交替执行 * }catch (InterruptedException e){//采用异常是因为,休眠可以被打断 * e.printStackTrace(); * } */ } System.out.println(Thread.currentThread().getName()+"正在运行"); } } public class TestRunnable { public static void main(String[] args){ PrintRun r1 = new PrintRun(); Thread t1 = new Thread(r1); t1.start(); try { t1.join();//抢先执行。抢占资源,join里面参数是执行抢占的时间 }catch (InterruptedException e){ e.printStackTrace(); } } }

 

 

 

 

 

 

package com.com.binbin.runnable; /** * 线程优先级 * @author binbinarvin * @create 2019-01-25 */ class PrintRun implements Runnable{ int i = 1; @Override public void run() { while(i<15){ System.out.println(Thread.currentThread().getName()+"运行"+(i++)); } System.out.println(Thread.currentThread().getName()+"正在运行"); } } public class TestRunnable { public static void main(String[] args){ //获取主线程的优先级Main方法的:Thread.currentThread().getPriority() System.out.println("main的优先级为:"+Thread.currentThread().getPriority()); PrintRun r1 = new PrintRun(); Thread t1 = new Thread(r1); t1.setPriority(5); //虽然它优先级高,但是它先后运行不确定,之所以会先运行,线程的运行还会被CPU以及环境的设置影响 t1.start(); PrintRun r2 = new PrintRun(); Thread t2 = new Thread(r2); t2.setPriority(10);//t1.setPriority(Thread.MAX_PRIORITY); t2.start(); System.out.println("main"); } }

 

 

 

package com.imooc.queue; /** * 同步与通信,(SYNCHRONIZED && WAIT && NOTIFY) * * @author binbinarvin * @create 2019-01-25 */ public class Producer implements Runnable{     Queue queue;     Producer(Queue queue){         this.queue=queue;     }     @Override     public void run() {         int i=0;         while(true){             queue.set(i++);             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }        } } public class Consumer implements Runnable{     Queue queue;     Consumer(Queue queue){         this.queue=queue;     }     @Override     public void run() {         while(true){             queue.get();             try {                 Thread.sleep(1000);             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }     }   } / public class Queue {     private int n;     boolean flag=false;//用于判断是否先生产后消费          public synchronized int get() {         if(!flag){             try {                 wait();//等待会导致死锁             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }         System.out.println("消费:"+n);         flag=false;//消费完毕,容器中没有数据         notifyAll();//解开死锁         return n;     }     public synchronized void set(int n) {         if(flag){             try {                 wait();             } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }         System.out.println("生产:"+n);         this.n = n;         flag=true;//生产完毕,容器中已经有数据         notifyAll();     }   } public class Test {     public static void main(String[] args) {         Queue queue=new Queue();         new Thread(new Producer(queue)).start();//三步合一         new Thread(new Consumer(queue)).start();     } }

 

 

 

 

 

 

 

 

 

 

 

start()

  start方法是Thread 类的方法,在这个方法中会调用native方法(start0())来启动线程,为该线程分配资源。

sleep()

  sleep方法有2个方法。

public static native void sleep(long millis) throws InterruptedException; public static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); }

  看了源码,发现第二个纳秒级别的没什么用,实际上还是毫秒级别。sleep方法在进入阻塞队列时不会释放当前线程所持有的锁。

yield()

  该方法会让当前线程交出cpu权限,但是不能确定具体时间,和sleep方法一样不会释放当前线程所持有的锁,该方法会让线程直接进入就绪状态,很好理解。目的是为了让同等优先级的线程获得cpu执行的机会。

join()

  该方法是让当前线程阻塞,直到调用该方法的线程执行完毕。源码分析

public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }

  这个是join的源码,代码很清晰,如果调用该方法的对象线程已启动,那么当前线程释放该对象锁,并进入条件等待队列里面,等待改线程执行完(线程如果在同步代码块中结束会自动调用notifyAll()方法来唤醒等待队列里面的线程)

wait() ,notifyAll(),notify()

  这3个方法一般一同出现。且都是Object类的方法,用来辅助操作线程类。这3个方法都必须在同步代码块中,不然就会报错。

  wait()方法会让当前线程释放锁,并进入到条件等待队列。

  notify()方法会随机唤醒条件等待队列的任意一个线程,并将其放到锁池里面。

  notifyAll()方法则是唤醒条件等待队列的所有线程,并将其都放到锁池里面。

  而锁池里面的线程来竞争所需要的对象锁,成功获取到锁的线程将加入到就绪队列里面。

interrupt(),isInterrupted(),interrupted()

  这3个方法表示线程的中断,这个很有意思,分多钟情况讨论。(在java中,中断不是强制停止改线程,而是给线程一个信号,让其自行处理何时退出)

  isInterrupted:就是返回对应线程的中断标志位是否为true。

  interrupted:返回当前线程的中断标志位是否为true,但它还有一个重要的副作用,就是清空中断标志位,也就是说,连续两次调用

  interrupted(),第一次返回的结果为true,第二次一般就是false 。

  interrupt:表示中断对应的线程。

  中断线程分情况讨论:

  1.还没start,或者已经结束,无效果

  2.运行中,中断无效,直到只能设置个中断位,直到线程走完或者进入阻塞。

  3.锁池,中断无效。

  4.阻塞,等待,会抛出异常,可以中断。

(io等待大多都是可以中断的,但是inputStream的read不会相应中断。)中断不好使,因此最好自己在线程类里面提供关闭方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值