java 线程
1 进程和线程
进程:对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。线程:有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。
进程和线程的关系:
1) 一个程序至少有一个进程,一个进程至少有一个线程.
2) 进程的概念大于线程。
3) 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
2 线程的运行过程
① 创建线程:Thread类继承;实现接口runnable,只要new一个Thread对象,一个新的线程也就出现了。每个线程都是通过某个特定的Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。
优先选择实现Runnable接口这种方式去开辟一个新的线程,因为java是单继承。
② join() : thread 调用 join()方法会使线程合并,顺序执行,只有当当前的线程执行完成之后,执行后续的程序。
join方法源码:
1 public final synchronized void join(long millis) 2 throws InterruptedException { 3 long base = System.currentTimeMillis(); 4 long now = 0; 5 6 if (millis < 0) { 7 throw new IllegalArgumentException("timeout value is negative"); 8 } 9 if (millis == 0) { //如果时执行的join(0) 10 while (isAlive()) { //如果线程是运行状态,就会执行下面的等待 11 wait(0); 12 } 13 } else { //如果是执行的join(time) 14 while (isAlive()) { //如果线程时运行状态 15 long delay = millis - now; 16 if (delay <= 0) { 17 break; 18 } 19 wait(delay); //等待delay时间后自动返回继续执行 20 now = System.currentTimeMillis() - base; 21 } 22 } 23 }
wait(0) 则为让其一直等待。join方法本质就是利用上面的线程实例作为对象锁的原理,当线程终止时,会调用线程自身的notifyAll()方法,通知所有等待在该线程对象上的线程的特征。
③ sleep()方法:sleep()方法是在Thread类里面声明的一个静态方法,推荐使用Thread.sleep()的格式进行调用。调用当前线程会从“运行状态”进入到“休眠(阻塞)状态”,此时不会释放锁,sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。
④ wait()、notify()和notifyAll() : 都为Object 方法,完成线程之间的互相通信。
1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须是拥有此对象的monitor(即锁)。
3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程。
4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程。
只有当前线程拥有了对象锁才能释放锁。
⑤yiled() 方法:当前执行的线程就让出来让另一个在执行run()方法的线程来优先执行
3 生产者消费者
1 package com.cn.thread; 2 3 4 //生产者 和 消费者 5 public class ProducersAndCustomersTest { 6 7 public static void main(String[] args) { 8 9 Syncstack s1 = new Syncstack(); 10 Thread p = new Thread(new Produce(s1)); 11 p.start(); 12 Thread p2 = new Thread(new Produce(s1)); 13 p2.start(); 14 Thread c = new Thread(new Customer(s1)); 15 c.start(); 16 Thread c2 = new Thread(new Customer(s1)); 17 c2.start(); 18 19 try { 20 Thread.sleep(5000); 21 } catch (InterruptedException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 } 26 } 27 28 //生产方法 和 消费方法 29 class Syncstack{ 30 private static int index = 0; 31 32 private char[] datas = new char[6]; 33 //添加 34 public synchronized void push(char c){ 35 if(index == datas.length){ 36 try { 37 this.wait(); 38 } catch (InterruptedException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 } 43 44 this.notify(); //唤醒 45 if(datas.length<=6){ 46 datas[index] = c; 47 } 48 index++; 49 } 50 51 //删除 52 public synchronized char pop(){ 53 if(index == 0){ 54 try { 55 this.wait(); 56 } catch (InterruptedException e) { 57 // TODO Auto-generated catch block 58 e.printStackTrace(); 59 } 60 } 61 62 this.notify(); 63 if(index > 0){ 64 index--; 65 return datas[index]; 66 } 67 return 0; 68 } 69 } 70 71 //生产者类 72 class Produce implements Runnable{ 73 Syncstack stack; 74 public Produce(Syncstack s){ 75 stack = s; 76 } 77 public void run(){ 78 79 for(int i = 0; i< 20; i++){ 80 char c =(char)(Math.random()*26+'A'); 81 stack.push(c); 82 System.out.println("produced:"+c); 83 84 try { 85 Thread.sleep((int)(Math.random()*1000)); 86 } catch (InterruptedException e) { 87 // TODO Auto-generated catch block 88 e.printStackTrace(); 89 } 90 } 91 } 92 } 93 94 95 //消费者 96 class Customer implements Runnable{ 97 Syncstack stack; 98 public Customer(Syncstack s){ 99 stack = s ; 100 } 101 public void run(){ 102 for(int i = 0;i< 20 ;i++){ 103 char c = stack.pop(); 104 System.out.println("消费者:s 消费了:"+c); 105 106 try { 107 Thread.sleep((int)(Math.random()*1000)); 108 } catch (InterruptedException e) { 109 // TODO Auto-generated catch block 110 e.printStackTrace(); 111 } 112 } 113 } 114 }
