Java笔记3_多线程

知识:

1,线程与进程:进程是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。一个进程中至少有一个线程。Java VM启动的时候会有一个进程java.exe,该进程至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程成为主线程。JVM启动的时候,还要产生一个垃圾回收机制的线程。多线程存在的意义:让程序中的各个部分产生同时的效果,一个进程中多个线程好像同时进行。

2,创建线程方法1---继承Thread类:(java.lang.Thread)步骤:继承Thread类;复写Thread类中的run方法;调用线程的start方法(该方法的作用:启动线程,调用run方法)多线程程序就相当于多个线程抢资源,因此随机性比较大

3,创建线程方法2---实现runnable接口:步骤:1,     定义类实现Runnable接口;2, 覆盖Runnable接口中的run方法;3,       通过Thread类建立线程对象;4,     将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数;5,    调用Thread的start方法开启线程并调用Runnable接口子类的run方法

4,多线程安全问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误;解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中其他线程不可以参与执行,java提供的解决方式是同步

5,同步代码块

Synchronized(对象){

需要被同步的代码

对象的参数是一个锁,同步锁,对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。

同步的前提:必须要有两个或者两个以上的线程;必须是多个线程使用同一个锁。

同步好处:解决了多线程的安全问题;弊端:多个线程需要判断锁,较为消耗资源

6,同步函数

       同步代码块的同步部分可以直接声明在函数上;而不是放在run上,放在run上就只有Thread0线程运行,而没有另一个线程运行;

       同步函数的锁是this,因为函数被这个所属对象引用。

       同步解决问题的方法:找到同步代码;明确共享数据;明确那部分的代码是操作共享数据的;带sleep测试可以找出程序中的问题

7,静态同步函数

       静态同步函数的锁是class对象,因为静态没对象,而是通过类直接调用;而且静态进内存是在类加载进之后,对象创建之前;

8,单例设计模式中懒汉模式的同步处理:

       懒汉式:

       Class Single{

       Private static Single s=null;

       Private Single(){}

Public staticSingle getInstance(){

              If(s==null){            //用双重判断的方式减少判断锁的次数,解决低效

              Synchronized(Single.class)   //静态的锁是当前的class文件

{     If(s==null){

S=new Single();

}

}

Return s;

}

9,死锁

       同步中的嵌套同步,一直获不到资源

       一个死锁程序:程序中。。。

10,线程间通信

       多线程之间操作同一个资源,但是操作的动作不同。

       等待唤醒机制:为了满足输出的顺序性,选择使用标记位,进入后进行判断,如果存入,就修改标记位,如果打印,打印之后再修改回去。

wait,notify,notifyAll:1:wait:让线程等待2:notify:唤醒线程池中的第一个线程3:notifyAll:唤醒线程池中的所有线程

为什么这些方法定义在了Object类中?1:这些方法存在与同步中。2:使用这些方法时必须要标识所属的同步的锁。3:锁可以是任意对象,所以任意对象调用的方法一定定义Object类中。

wait(),sleep()有什么区别?wait()可有无参数的调用, 而sleep必须指定睡眠时间,但是有些时候,睡眠时间不好确定,这个时候就可以使用wait.;wait:释放了执行权,释放锁,sleep:释放了执行权,不释放锁;sleep有醒过来的时候,而wait可能醒不了.

11,生产者消费者

资源:里面有同步的set和get方法,set是供多个生产者加入,get是让多个消费者得到;

生产者:实现runnable接口,一个私有的资源,初始化传进一个资源实例,set操作放进复写的run里面。

消费者:实现runnable接口,一个私有的资源,初始化传进一个资源实例,get操作放进复写的run里面。

代码参照后面:

12,停止线程:通过stop方法停止线程.但是这个方法过时,所以不推荐使用;开启多线程,运行代码通常是循环结构,只要控制住循环,就可以run方法结束,也就是线程结束;

Thread.currentThread().getName():获得当前线程名字;

在run外部写上修改标记位。run判断不通过就退出了;特殊情况:当线程处于了冻结状态,就不会读取到标记,那么线程就不会结束;当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除,强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束(Thread里面的方法 interrupt  ------中断线程);

13,守护线程

Void setDaemon(Boolean on)  将线程标记为守护线程或用户线程;当正在运行的线程都是守护线程时,JVM退出

14,join方法

       临时抢夺CPU执行权,用于临时加入线程执行

       特点:当A线程执行到B线程的join方法时,A就会等待,当B线程都执行完,A才会执行。Join可以用来临时加入线程执行

15,优先级-yield方法

打印线程时调用toString()方法会按照[线程名称,优先权,线程所在的组名称]输出;默认优先级为5,主线程的优先级就是5;

Static void    yield() 暂停当前正在执行的线程对象,并执行其他线程

  T1.setPriority(Thread.MAX_PRIORITY).设置成线程的最高优先级10

       优先级越高,运行的概率越高

      

16,线程的状态以及线程的常用方法:

线程的状态有就绪状态,运行状态,等待状态,休眠状态,终止状态,当条件齐备的时候就绪状态的线程就会开始执行。

wait()/notify()/notifyAll(): wait()之后线程释放锁进入等待状态,就绪状态的线程才可以利用锁;进入等待状态的线程只有通过notify()/notifyAll()才能够被唤醒(当条件发生变化)。和synchronized连用。

sleep(): 不释放琐,只是作一段时间的休眠,休眠完后继续执行。

yield(): 释放锁,使当前线程马上回到就绪状态,也可能马上在执行。

17,改进:

jdk1.5以后将同步和锁封装成了对象进行了优化。

Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成了显示锁操作。同时更为灵活,可以一个锁上加上多组监视器。

Condition接口:出现替代了object中的wait  notify  notifyAll方法。将这些监视器方法单独进行了封装,变成Condition监视器对象。可以和任意的锁进行组合。

将生产者消费者的代码优化。。

问题:

1,为什么要覆盖Thread类的run方法呢?Thread类用于描述线程。该类就定义了一个功能,用于存储线程要的代码,该存储功能就是run方法;也就是说,thread类中的run方法,用于存储线程要运行的代码;复写Thread类中的run方法 目的:将自定义的代码存储在run方法,让线程运行。

2,为什么要将Runnable接口的子类对象传递给Thread的构造函数?

因为自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法,就必须明确该run方法所属对象。

3,实现方式和继承方式有什么区别呢?继承Thread:线程代码存放Thread子类run方法中;实现Runnable,线程代码存放在接口的子类的run方法。实现的方式能避免单线程的局限性,所以建议使用实现接口的方法;Thread本身也实现Runnable接口

4,什么时候使用多线程?当某些代码同时被执行时,就用单独的线程进行封装,独立运算;多个之间相互不相干的时候封装成多线程。

程序:

死锁程序:http://zhidao.baidu.com/question/7744377.html 

 1 class Test implements Runnable
 2 {
 3     private boolean flag;
 4     Test(boolean flag)
 5     {
 6         this.flag = flag;
 7     }
 8 
 9     public void run()
10     {
11         if(flag)
12         {
13             while(true)
14             {
15                 synchronized(MyLock.locka)
16                 {
17                     System.out.println(Thread.currentThread().getName()+"...if locka ");
18                     synchronized(MyLock.lockb)
19                     {
20                         System.out.println(Thread.currentThread().getName()+"..if lockb");                    
21                     }
22                 }
23             }
24         }
25         else
26         {
27             while(true)
28             {
29                 synchronized(MyLock.lockb)
30                 {
31                     System.out.println(Thread.currentThread().getName()+"..else lockb");
32                     synchronized(MyLock.locka)
33                     {
34                         System.out.println(Thread.currentThread().getName()+".....else locka");
35                     }
36                 }
37             }
38         }
39     }
40 }
41 
42 
43 class MyLock
44 {
45     static Object locka = new Object();
46     static Object lockb = new Object();
47 }
48 
49 class  DeadLockTest
50 {
51     public static void main(String[] args) 
52     {
53         Thread t1 = new Thread(new Test(true));
54         Thread t2 = new Thread(new Test(false));
55         t1.start();
56         t2.start();
57     }
58 }
59 /*两个锁是相互使用,很容易产生死锁,但也有可能会和谐*/

生产者消费者程序:

http://bbs.itheima.com/forum.php?mod=viewthread&tid=33523&page=1#pid195933

 1 /*
 2 生产者,消费者。
 3 多生产者多消费者。 
 4 
 5 if判断标记只有一次,会导致不该运行的线程运行了,会出现数据错误的情况。
 6 while判断标记,解决了线程获取执行权后,是否要运行。
 7 
 8 notify:只能唤醒一个线程,如果唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
 9 notifyAll 解决了本方线程一定会唤醒对方线程的问题。
10 
11 */
12 class Resource2{
13         private String name;
14         private int count = 1;
15         private boolean flag = false;
16         public synchronized void set(String name){
17                 while(flag)
18                         try{this.wait();}
19                         catch(InterruptedException e){}
20                 this.name = name + count;
21                 count++;
22                 System.out.println(Thread.currentThread().getName()+"...生产者"+this.name);                
23                 flag = true;
24                 notifyAll();
25         }
26         public synchronized void get(){
27                 while(!flag)
28                         try{this.wait();}
29                         catch(InterruptedException e){}
30                 System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
31                 flag = false;
32                 notifyAll();
33         }
34 }
35 
36 class Producer implements Runnable{
37         Resource2 r;
38         Producer(Resource2 r){
39                 this.r = r;
40         }
41         
42         public void run(){
43                 while(true){
44                         r.set("烤鸭");
45                 }
46         }
47 }
48 
49 class Consumer implements Runnable{
50         
51         Resource2 r;
52         Consumer(Resource2 r){
53                 this.r = r;
54         }
55         public void run(){
56                 while(true){
57                         r.get();
58                 }
59         }
60 }
61 
62 public class ConsumerDemo2 {
63         public static void main(String[] args) {
64                 Resource2 r = new Resource2();
65                 
66                 Producer pro = new Producer(r);
67                 Consumer con = new Consumer(r);
68                 
69                 Thread t0 = new Thread(pro);
70                 Thread t1 = new Thread(pro);
71                 Thread t2 = new Thread(con);
72                 Thread t3 = new Thread(con);
73                 
74                 t0.start();
75                 t1.start();
76                 t2.start();
77                 t3.start();                
78         }
79 }

单例设计模式懒汉式:

 1 /*
 2 单例设计模式。
 3 
 4 
 5 */
 6 //饿汉式。
 7 /*
 8 class Single
 9 {
10     private static final Single s = new Single();
11     private Single(){}
12     public static Single getInstance()
13     {
14         return s;
15     }
16 }
17 */
18 
19 
20 //懒汉式
21 
22 class Single
23 {
24     private static Single s = null;
25     private Single(){}
26 
27 
28     public static  Single getInstance()
29     {
30         if(s==null)
31         {
32             synchronized(Single.class)
33             {
34                 if(s==null)
35                     //--->A;
36                     s = new Single();
37             }
38         }
39         return s;
40     }
41 }
42 
43 class SingleDemo 
44 {
45     public static void main(String[] args) 
46     {
47         System.out.println("Hello World!");
48     }
49 }

同步函数例子:

 1 /*
 2 需求:
 3 银行有一个金库。
 4 有两个储户分别存300员,每次存100,存3次。
 5 
 6 目的:该程序是否有安全问题,如果有,如何解决?
 7 
 8 
 9 如何找问题:
10 1,明确哪些代码是多线程运行代码。
11 2,明确共享数据。
12 3,明确多线程运行代码中哪些语句是操作共享数据的。
13 */
14 class Bank
15 {
16     private int sum;
17     //Object obj = new Object();
18     public synchronized void add(int n)
19     {
20         //synchronized(obj)
21         //{
22             sum = sum + n;
23             try{Thread.sleep(10);}catch(Exception e){}
24             System.out.println("sum="+sum);
25         //}
26     }
27 }
28 class Cus implements Runnable
29 {
30     private Bank b = new Bank();
31     public void run()
32     {        
33         for(int x=0; x<3; x++)
34         {
35             b.add(100);
36         }
37     }
38 }
39 class  BankDemo
40 {
41     public static void main(String[] args) 
42     {
43         Cus c = new Cus();
44         Thread t1 = new Thread(c);
45         Thread t2 = new Thread(c);
46         t1.start();
47         t2.start();
48     }
49 }
原文地址:https://www.cnblogs.com/yys369/p/2822470.html