黑马程序员_java_多线程2

时间:2022-04-08 12:19:29

------- android培训java培训、期待与您交流! ----------

同步函数:

show();方法本身没有同步性,但我们加上sychronized标记后就具备了同步性。

class Ticket implements Runnable  
{  
    private int num = 100;  
    //private Object obj = new Object(); 同步函数使用的锁是this 这里我们将boject注释掉,程序也没问题,
    public  void run()  
    {  
        while(true)  
        {  
            show();  
        }  
    }  
    //同步函数  
    public synchronized void show()  
    {  
        if(num>0)  
        {  
            try{Thread.sleep(10);}catch(InterruptedException e){}  
            System.out.println(Thread.currentThread().getName()+".....sale....."+num--);  
        }  
    }  
}  
class TicketDemo3   
{  
    public static void main(String[] args)   
    {  
        Ticket t = new Ticket();  
          
        //创建线程对象。  
          
        Thread t1 = new Thread(t);  
        Thread t2 = new Thread(t);  
        Thread t3 = new Thread(t);  
        Thread t4 = new Thread(t);  
  
        t1.start();  
        t2.start();  
        t3.start();  
        t4.start();  
    }  
}  
那么同步函数和同步代码块的区别是:①书写,同步函数书写简单②用的锁不一样,同步函数使用的锁是this;同步代码块使用的锁是任意对象

然而当静态方法在编译的时候还没有this也没有对象,所以静态方法若要同步,使用的锁是该类字节码文件对象----表示方式:类名.class

死锁

最常见的死锁情况,同步的嵌套:同步中还有同步,两个同步用的不是一个锁。

 我们应当,尽量避免同步嵌套的情况。

class Clock {  //锁使用的2个对象
    public static Clock locka = new Clock();  
    public static Clock lockb = new Clock();  
}  
class DeadLock implements Runnable {  
    private boolean flag;  //定义Boolean变量
    public DeadLock(boolean flag){  
        this.flag = flag;  
    }   
    @Override  
    public void run() {  
        if(flag){  //让2个线程进入不同的锁当中
            while(true){  
                synchronized(Clock.locka){  //线程T1在locka的锁准备进入lockb的锁中
                    System.out.println(".................if locka");  
                    synchronized(Clock.lockb){  
                        System.out.println(".................if lockb");  
                    }  
                }  
            }  
        }  
        else{  
            while(true){  
                synchronized(Clock.lockb){  线程t2在lockb的锁中准备进入locka的锁中
                    System.out.println("-------------------------else lockb");  
                    synchronized(Clock.locka){  
                        System.out.println("----------------------else locka");  
                    }  
                }  
            }  
        }  
    }     
}   
public class DeadLockTest {    
    public static void main(String[] args) {  
        DeadLock d1 = new DeadLock(true);  //创建对象,并设定Boolean值
        DeadLock d2 = new DeadLock(false);  <span style="font-family: Arial;">//创建对象,并设定Boolean值</span>       
        Thread t1 = new Thread(d1);  //创建线程,传人对象
        Thread t2 = new Thread(d2);  
        t1.start();  //开启线程
        t2.start();  
          }  
}  
例中,当先线程当t1 拿到 Clock.locka , 当线程t2 拿到 Clock.lockb时,线程t1 需要  Clock.lockb 来继续运行,线程t2 需要 Clock.locka 来继续运行,而此时锁中都有运行着的线程,对方不能进入,造成了死锁的状况。

java中的等待唤醒机制

class Resource {  
    private String name ;  
    private String sex;  
    private boolean flag = false;      
    public synchronized void set(String name , String sex){         
        if(flag)  
            try {  
                wait();  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }          
            this.name = name;  //设置成员变量  
            this.sex = sex;            
            flag = true;   //设置之后,Resource中有值,将标记该为 true ,             
            this.notify(); //唤醒output     
    }  
    public synchronized void out(){  
        if(!flag)  
            try {  
                wait();  
            } catch (InterruptedException e) {                 
                e.printStackTrace();  
            }             
        System.out.println("The name is : " + name + " &&  The sex is : " + sex); //输出线程将数据输出       
        flag = false;//改变标记,以便输入线程输入数据                   
        this.notify(); //唤醒input,进行数据输入     
    }   
}   
class Input implements Runnable {   
    private Resource r;  
    public Input(Resource r){  
        this.r = r;  
    }  
    public void run() {  
        int count = 0 ;   
        while(true){  
            if(count == 0){  
                r.set("Tom", "man");  
            }else{  
                r.set("Lily", "woman");  
            }            
            count = (count + 1)%2; //每执行到一次设置一次name和性别。    
        }  
    }  
}   
class Output implements Runnable {   
    private Resource r ;  
    public Output(Resource r ){  
        this.r = r;  
    }   
    public void run() {  
        while(true){  
            r.out();  
        }   
    }  
}  
public class ResorseDemo {   
    public static void main(String[] args) {        
        Resource r = new Resource(); //资源对象          
        Input in = new Input(r); //任务对象    
        Output out = new Output(r);        
        Thread t1 = new Thread(in); //线程对象    
        Thread t2 = new Thread(out);         
        t1.start();  //开启线程t1   
        t2.start();       
    }  
}  

在这个例子中,我们应用了等待唤醒机制:input() 和output()利用wait()和notify();及设置Boolean值来交替输入和打印一组姓名----年龄。

线程的优先级

当有多个线程同时处于可执行状态(就绪状态)哄抢CPU控制权时
优先级能够使得优先级高的线程有更大的机会获得 CPU 控制权,优先级低的线程机会要小

JAVA 里面定义了10级

可以用setPriority来设置线程的优先级,getPriority取得线程的优先级:

import sharevar.Machine;
public class priority extends Thread {
    private static StringBuffer log=new StringBuffer();
    private static int count=0;  
    public void run() {
        for (int a=0;a<20;a++) {
            log.append(currentThread().getName()+":"+a);
            if (++count %10==0) log.append("\n");
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Machine m1=new Machine();
        Machine m2=new Machine();
        m1.setName("m1");
        m2.setName("m2");
        Thread main=Thread.currentThread();   //获得主线程
        //查看和设置线程的优先级
        System.out.println("default priority of main:"+main.getPriority());
        //打印m2线程默认优先级
        System.out.println("default priority of m1:"+m1.getPriority());
        //打印m2线程默认优先级
        System.out.println("default priority of m2:"+m2.getPriority());    
        m2.setPriority(Thread.MAX_PRIORITY);
        m1.setPriority(Thread.MIN_PRIORITY);
        m1.start();//开启线程
        m2.start();
        System.out.println(log);
    }

}