1 进程和线程

进程:对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

线程:有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

进程和线程的关系:

1) 一个程序至少有一个进程,一个进程至少有一个线程.

2) 进程的概念大于线程。

3) 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

4) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

2 线程的运行过程

  java 线程 随笔    

① 创建线程: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 }

 

 

 

 

 

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄