javase_19(多线程)

进程:

进程是具有一定独立功能的程序关于某个数据集合上的一次运动.

 

线程:

线程是进程里面的一个实体,CPU调度或分派的基本单位

 

进程与线程之间的区别:

总而言之,一个进程里面可以有多个线程,但是一个进程至少有一个线程

 

多线程存在的意义:

程序允许有多个线程并发,提供程序的运行的效率   

 

线程的创建方式:

new Thread().start();

 

 

多线程的应用:

Sun公司为我们提供了Thread类来实现线程

通过new Thread()来创建一个线程对象.

定义一个类继承Thread,子类就有了线程的功能

创建Thread类的子类的对象,也可以创建一个线程.

 

线程的启用:

Thread类定义了run()方法,用于启动当前的线程

在启用当前的线程的时候,虚拟机会自动调用于run()方法

 

线程的其他方法:

sleep:使线程进入到睡眠的状态,需要唤醒的时间,会抛异常

setDaemon:将当前的线程设置为一个后台的线程,但主线程结束,它也会跟着结束

Join:合并一个线程,会抛出异常-->合并进来,join被谁调用,谁就执行.

currentThread:获取当前运行的线程.

 

package com.javami.kudy.DemoThread;

public class ThreadTest {
    
    public static void main(String[]args)
    {
        int num = 0;
        MyThread mt = new MyThread();
        //为当前的线程起名字
        mt.setName("kudy-0");
        mt.setDaemon(true); //设置为后台线程,但主线程执行完毕.后台线程也会跟着退出
        mt.start();
        //一个进程至少有一个主线程
        while(true)    
        {
            if(num++>10)
                break;
            try{mt.join();}catch(Exception e){e.printStackTrace();}
            try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+"Main()");
        }
        
    }
}


class MyThread extends Thread
{
    @Override
    public void run()
    {
        while(true)
        {
            //获取当前线程
            try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+" run()");
        }
    }
}

创建线程的方式二:

 

实现Runnable接口

子类覆盖父类中的run()犯法

通过Thread类创建线程,并且实现了Runnable接口中的子类

对象作为参数传递给Thread类型类的构造函数

 

这样做有什么好处:

线程开了,并且只是处理一个对象.用到了组合模式

 

为什么需要用到同步代码块或者同步函数:

 

由于程序在执行的时候,会出现线程不安全的问题,所以我们需要用到同步函数或者同步代码块.

导致线程不安全的注意问题:

 

1.多个线程随机访问延时

2.线程随机性

 

同步代码块:

Synchronized(对象)  //锁旗标 0开 1

{

需要同步的代码;

}

同步代码可以解决安全的问题根本原因在于对象上面,该对象如同锁的功能.

 

同步函数:

在函数上面加上synchronized修饰即可.

Public synchronized void sale()

{

//同步代码块使用的锁是this这个锁

}

死锁:

发生在相互调用的情况下,一个同步函数里要用到和同步代码块相同的锁,同步代码块又去调用函数,就用到函数的锁,两者都会锁死,发生死锁的问题.

 

 1 package com.javami.kudy.DemoThread;
 2 
 3 public class TicketsSale {
 4 
 5     /**
 6      * @param args
 7      * 多线程售票:同时开启4个线程售票
 8      * 
 9      * 线程安全问题在理想的状态下,不容易出现,但一旦出现就是对软件的影响是非常之大
10      * Thread-1  -1
11        Thread-0  0
12        Thread-3  1
13        ----↓
14        同步代码块
15        与同步函数:
16        
17      */
18     public static void main(String[] args) {
19         SaleThread st = new SaleThread();
20         
21         //4个进程产生
22         new Thread(st).start();
23         new Thread(st).start();
24         new Thread(st).start();
25         new Thread(st).start();
26     }
27 }
28 
29 class SaleThread implements Runnable
30 {
31     String lock = ""; //锁期标
32     private int tickets = 10; //10张车票
33     @Override
34     public void run()
35     {
36         
37         while(true)  // 0 1 2 3 等待我执行完毕别的线程才去抢
38         {
39             synchronized(lock)
40             {
41             if(tickets<1)
42                 break;
43             try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
44             System.out.println(Thread.currentThread().getName()+"  "+tickets--);
45             }
46         }
47     }
48 }

同步的特点:

 

1.同步需要两个或者两个以上的线程.

2.多个线程使用的是同一把锁

3.为满足这两个条件,不能称其为同步.

 

同步的弊端:

 

1.当线程相当多的时候,因为每个线程都会去判断同步上的锁.这是很消耗资源的,判断该锁是否被锁上.如果锁上.需要等锁上的开了才可以互相抢进去.

无形中可以减低了程序运行的效率.

 

 1 package com.javami.kudy.DemoThread;
 2 
 3 public class TicketsSale1 {
 4     /*
 5      * 使用同步函数与同步代码块来实现4个线程
 6      */
 7     public static void main(String[]args)
 8     {
 9         SaleThread1 st = new SaleThread1();
10         new Thread(st).start();
11         new Thread(st).start();
12         st.lock = "ok";
13         try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
14         new Thread(st).start();
15         new Thread(st).start();
16     }
17 }
18 
19 class SaleThread1 implements Runnable
20 {
21     String lock = " ";
22     private int num = 100;
23     public void run()
24     {
25         if(lock.equals("ok"))
26         {
27             while(true)
28             {
29                 sale();
30             }
31         }else
32         {
33             while(true)
34             {
35                 synchronized (this) {
36                     if(num<1)
37                         return;
38                     System.out.println(Thread.currentThread().getName()+"else"+num--);
39                 }
40             }
41         }
42     }
43     
44     
45     private synchronized void sale() {
46             if(num<1)
47                 return;
48             System.out.println(Thread.currentThread().getName()+"if"+num--);
49     }
50 }

 

线程间的通信:

 

两个线程之间可以相互的通信

一个线程可以通过wait方法等待,这时CPU会让给别程

通过进行等待的线程需要其他线程调用notify()方法唤醒.

 

 1 package com.javami.kudy.DemoThread;
 2 
 3 /*
 4  * 通信必须要在同步函数里面去解决的
 5  */
 6 class SQL
 7 {
 8     public String name;
 9     public String sex;
10     public boolean  b = false;
11 }
12 class DBA implements Runnable
13 {
14     SQL sql ;
15     public DBA(SQL sql)
16     {
17         this.sql = sql;
18     }
19     public void run()
20     {
21         int num = 0;
22         while(true)
23         {
24             synchronized (sql) {
25             if(sql.b) //为真.我等待,让给别的进程~
26                 try{sql.wait();}catch (Exception e) {e.printStackTrace();}
27             if(num ==0)
28             {
29                 sql.name = "小细";
30                 sql.sex = "男";
31             }else
32             {
33                 sql.name = "美怡";
34                 sql.sex = "女";
35             }
36                 num = (num+1)%2;  //实现了来回打印
37                 sql.b = true;
38                 sql.notify(); //等待完毕需要把你唤醒~
39             }
40         }
41     }
42 }
43 
44 /*
45  * 编码员
46  */
47 class Coder implements Runnable
48 {
49     SQL sql ;
50     public Coder(SQL sql)
51     {
52         this.sql = sql;
53     }
54     public void run()
55     {
56         while(true)
57         {
58             synchronized (sql) {
59                 if(!sql.b) //如果为假-->我等待
60                 try{sql.wait();}catch(Exception e){e.printStackTrace();}
61                 System.out.print(sql.name+" ");
62                 System.out.println(sql.sex+" ");
63                 sql.b = false; //标记为假~~并且把这个进程唤醒
64                 sql.notify();
65             }
66         }
67     }
68 }
69 public class SqlThread {
70 
71     /**
72      * 模仿数据库的操作,实现边读取,边打印
73      */
74     public static void main(String[] args) {
75             SQL sql = new SQL();
76             DBA dba = new DBA(sql);
77             Coder cr = new Coder(sql);
78             new Thread(dba).start();  //一个线程交换位置
79             new Thread(cr).start(); //另外一个线程马上就打印出来
80     }
81 
82 }

思考:

wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?

wait(),sleep()有什么区别?

Wait():假设我同步代码块抢到啦.我执行wait()方法,就会让该线程等待.让别的线程执行.

Notiyf():唤醒等待中的线程-->下一个

notiyfyAll():  唤醒在此对象监视器上等待的所有线程。

Sleep():这个是去睡觉去啦~~~不需要你唤醒的,这家伙是自然醒.

使用1.5lockcondition解决存和取之间的通信问题

 

  1 package com.javami.kudy.DemoThread;
  2 
  3 import java.util.concurrent.locks.Condition;
  4 import java.util.concurrent.locks.Lock;
  5 import java.util.concurrent.locks.ReentrantLock;
  6 
  7 /*
  8  * 锁必须要一样,才能称得上同步
  9  */
 10 class MyArray1
 11 {
 12     private int[] arr = new int[10];
 13     private int savePos = 0;
 14     private int getPos = 0;
 15     private Lock lock = new ReentrantLock(); //创建一个锁
 16     private int count = 0;
 17     private Condition isFull = lock.newCondition(); //返回一个通信对象
 18     private Condition isEmpty = lock.newCondition();//返回的地址一样
 19     
 20     public void add(int num) throws InterruptedException
 21     {
 22         //但我执行慢的时候.我这个锁会开.开的时候.一看count==10等待..又抢,如果是你.你就等待.否则就是get  但是执行完毕一定要把当前的线程唤醒
 23         try
 24         {
 25             lock.lock();//开锁
 26             while(count==10)
 27                 isFull.await();//if等于10了,你就必须等待
 28             if(savePos==10)
 29                 savePos = 0;
 30             arr[savePos++] = num;
 31             count++;
 32         }finally
 33         {
 34             isEmpty.signal();//唤醒
 35             lock.unlock();
 36         }
 37     }
 38     
 39     public int get() throws InterruptedException
 40     {
 41         try
 42         {
 43             lock.lock(); //开锁
 44             while(count==0)
 45                 isEmpty.await();//等待
 46             if(getPos==10)
 47                 getPos = 0;
 48             count--; //不-- ~?  数组问题
 49             return arr[getPos++];
 50         }finally
 51         {
 52             isFull.signal();//等待的哥们.我去叫醒你啦~~
 53             lock.unlock();//开锁
 54         }
 55     }
 56 }
 57 public class ArrayThreadDemo {
 58     static int num = 1;
 59     public static void main(String[]args)
 60     {
 61         final MyArray1 ma = new MyArray1();
 62         new Thread(new Runnable(){
 63             @Override
 64             public void run() {
 65                 for(int i=0; i<30; i++)
 66                 {
 67                     try {
 68                         ma.add(num++);
 69                     } catch (InterruptedException e) {
 70                         // TODO Auto-generated catch block
 71                         e.printStackTrace();
 72                     }
 73                 }
 74             }
 75             
 76         }).start();
 77         new Thread(new Runnable(){
 78 
 79             @Override
 80             public void run() {
 81                 for(int i=0; i<30; i++)
 82                 {
 83                     try {
 84                         System.out.println(ma.get());
 85                     } catch (InterruptedException e) {
 86                         // TODO Auto-generated catch block
 87                         e.printStackTrace();
 88                     }
 89                 }
 90             }
 91             
 92         }).start();
 93         new Thread(new Runnable(){
 94             @Override
 95             public void run() {
 96                 for(int i=0; i<30; i++)
 97                 {
 98                     try {
 99                         ma.add(num++);
100                     } catch (InterruptedException e) {
101                         // TODO Auto-generated catch block
102                         e.printStackTrace();
103                     }
104                 }
105             }
106             
107         }).start();
108         new Thread(new Runnable(){
109 
110             @Override
111             public void run() {
112                 for(int i=0; i<30; i++)
113                 {
114                     try {
115                         System.out.println(ma.get());
116                     } catch (InterruptedException e) {
117                         // TODO Auto-generated catch block
118                         e.printStackTrace();
119                     }
120                 }
121             }
122             
123         }).start();
124 
125     }
126 }

 

今天的知识点回顾:

 

总体来说:但是今天的精神很好..最后面的一道题目要多加练习

第二同步函数是:必须执行完才执行到你,但是同步完毕后不保证以后线程()线程的情况.所以我们又用到 wait() 等待  唤醒(下一个的概念)

但是前提是同步函数里面使用.并且是同一把锁.注意锁的概念.程序要多敲-->后面理解毕竟不是很好.

 

 

posted @ 2012-08-24 23:30  自学_更是一种信仰  阅读(225)  评论(0编辑  收藏  举报