Java之线程基础与并发同步

1、实现线程

第一步:实现方法体

两种方法:

1)继承 java.lang.Thread 类,重写其 run() 方法。
   不推荐使用该方法,因为只能继承一个类,就不能继承其它的类了。

2)实现 java.lang.Runnable 接口,实现其 run() 方法。
   接口可以实现多个。
   其实 Thread 类也是实现了 java.lang.Runnable 接口。


第二步:运行

new 一个 java.lang.Thread 类,并调用其 start() 方法


说明:
在 jdk 1.5 中可以使用 java.util.concurrent 包中的类进行线程操作。
请阅读 java.util.concurrent包之Execuotor系列文章



2、例子:


例子一:


/*
         设计2个线程
         其中:
          1. 一个线程对数值增加 1
          2. 一个线程对数值减少 1
          3. 每个线程最多累计增加或减少9次
 */
public class TestSyncThread {
     
    public static void main(String[] args){
       
       int initNumber = 10;        
       Counter c = new Counter(initNumber);
       
       Thread t1 = new IncThread(c);
       Thread t2 = new Thread(new DecInterface(c));
       t1.start();
       t2.start();
    
    }
}

class Counter{
    private static int num = 0;
    public static int max = 100;
    
    public Counter (int init){
        num = init;
    }
    
    
    public synchronized void inc(int i){
        num ++;
        System.out.print("inc: ");
        System.out.println(num);
        
        if(i%10 == 9){
            this.notify();
            try {
                this.wait();                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        if(i==max){
            this.notify();
        }
        
    }
    
    public synchronized void dec(int i){
        num --;
        System.out.print("dec: ");
        System.out.println(num);
        
        if(i%10 == 9){
            this.notify();
            try {
                this.wait(); 
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        if(i == max){
            this.notify();
        }
    }
      
}
/*

    1、线程类中不要有 synchronized, wait(), notify() 等。这些是针对对象的。写在对象中。
    2、wait(), notify(), notifyAll() 方法需要放在 synchronized 修饰的方法体内,
             否则会提示:java.lang.IllegalMonitorStateException 
                           异常:该线程没有锁定对象却释放对象的锁。
             而线程执行 synchronized 修饰的语句块时,会拥有这个对象的锁。
    3、如果出现 java.lang.IllegalMonitorStateException:
       换句话说就是该线程未获得该对象监视器(即锁),而去调用 wait(), notify() 等操作。
*/
class IncThread extends Thread{
    Counter c;
    public IncThread( Counter c){
        this.c = c;
    }
    @Override
    public void run() {
        for(int i=0;i<=Counter.max;i++){
            System.out.print("i: "+i+ " - ");
            c.inc(i);
        }
    }
}


class DecInterface implements Runnable{    
    Counter c;    
    public DecInterface( Counter c){
        this.c = c;
    }    
    @Override
    public void run() {
        for(int i=0; i<=Counter.max; i++){
            System.out.print("i: "+i+ " - ");
            c.dec(i);            
        }        
    }
}






例子二:

尚学堂马士兵老师的:生产者消费者(注意英文注释的内容)


public class ProduceConsumer{  
    public static void main(String[] args){  
        SyncStack ss = new SyncStack();  
        Producer pro = new Producer(ss);  
        Consumer con = new Consumer(ss);  
        new Thread(pro).start();  
        new Thread(con).start();  
          
    }     
}  
  
class Product{  
    int id;  
    public Product(int id){  
        this.id = id;  
    }     
    public String toString(){  
        return "Product:" + id;  
    }  
}  
  
class SyncStack{  
    int index  = 0;  
    Product[] arrPro = new Product[6];  
      
    public synchronized void push(Product p){
        
        while (index == arrPro.length){  
            try {  
                this.wait();  // Causes the current thread to wait.
                /*                   
                   The current thread must own this object's monitor(lock),
                   then the thread releases ownership of this monitor(lock) 
                   and waits until another thread notifies threads which waiting on 
                   this object's monitor to wake up, either through a call to the notify() method 
                   or the notifyAll() method. 
                   The thread waits until it can re-obtain ownership of the monitor and resumes execution. 
                   
                 */
            } catch (InterruptedException e) {
                e.printStackTrace();  
            }  
        } 
        
        arrPro[index] = p;  
        index++;
       
        this.notify(); // send notification to threads to wake up for this object.
        /*
        Wakes up a single thread that is waiting on this object's monitor.
        
        If any threads are waiting on this object, one of them is chosen to be awakened. 
        The choice is arbitrary and occurs at the discretion of the implementation. 
        
        [NOTE: A thread waits on an object's monitor by calling one of the wait() methods.] 

        The awakened thread will not be able to proceed until the current thread 
        relinquishes(quit) the lock on this object. (
            so the "notify()" method can be put on the top of this method, it works fine.
        ).
        The awakened thread will compete in the usual manner with any other threads 
        that might be actively competing to synchronize on this object; 
        for example, the awakened thread enjoys no reliable privilege or disadvantage 
        in being the next thread to lock this object. 

        This method should only be called by a thread that is the owner of this object's monitor.         
        A thread becomes the owner of the object's monitor in one of three ways(
            Only one thread at a time can own an object's monitor.
        ): 
        
            1. By executing a synchronized instance method of that object. 
            2. By executing a synchronized statement body that synchronizes on the object. 
            3. By executing a synchronized static method of that class (for objects of type Class). 
      
     */
    }  
      
    public synchronized Product pop(){
        this.notify();
        while (index == 0){
            try {  
                this.wait();  
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        index--;  
        return arrPro[index];  
    }  
      
}  
  
class Producer implements Runnable{  
    SyncStack ss = null;  
    public Producer(SyncStack ss){ //持有SyncStack的一个引用  
        this.ss = ss;  
    }  
    @Override  
    public void run() {  
        for(int i=0; i<20; i++){  
            Product p = new Product(i);  
            ss.push(p);  
System.out.println("生产了:" + p);  
            try {  
                Thread.sleep(100);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
          
        }  
          
    }     
}  
  
class Consumer implements Runnable{  
  
    SyncStack ss = null;  
    public Consumer(SyncStack ss){ //持有SyncStack的一个引用  
        this.ss = ss;  
    }  
    @Override  
    public void run() {  
        for(int i=0; i<20; i++){  
            Product p = ss.pop();  
System.out.println("消费了:" + p);  
            try {  
                Thread.sleep(500);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
          
        }  
          
    }     
}  































-

猜你喜欢

转载自lixh1986.iteye.com/blog/2334526
今日推荐