多线程

来源:互联网 发布:直方图绘制软件 编辑:程序博客网 时间:2024/06/06 23:55
如果不重写Thread类的其他方法,创建子线程的最好方式是实现Runnable接口。

通常希望主线程再最后结束,isAlive()可以判断线程是否再运行,通常使用join()方法来等待线程结束。

实现线程线程间的互斥(同步):
  1. 使用synchronized关键字,当修饰代码块时,括号中要填写互斥(同步)对象的引用(悲观锁)
synchronized(){
}
  1. 使用显式的lock(java.util.concurrent.Lock)(乐观锁):        
      java.util.concurrent.Lock lock = new java.util.concurrent.ReentrantLock();
      lock.lock();
      lock.unlock();

  1. semaphore:当将信号量设置为1时,就能实现互斥操作
      java.util.concurrent.Semaphore = new Semaphore(1);

线程间的通信可以使用wait()、notify()、notifyAll()来使某一些线程等待或者唤醒,其中wait()使线程等待,notify()唤醒等待队列的某一线程,而notifyAll()唤醒等待队列里的所有线程(注意:这几种方法只能在synchronized上下文中调用
  • wait():通知调用线程放弃监视器并进入休眠,直到其他一些线程进入同一个监视器并调用notify()方法
  • notify():唤醒调用相同对象的wait()方法的线程
  • notifyAll():唤醒调用相同对象的wait()方法的所有线程,其中的一个线程将得到访问权限
使用wait()和notify()方法实现的生产者/消费者问题:
     仓库:
package producerConsumer;

public class Storage {
    private int storage = 0;
    // Indicate whose turn it is.

    private boolean flag = true;

    public synchronized void put(int amount) {
         try {
             // If it is get's turn
             while (flag) {
                 // wait until get finishes
                 wait();
             }
             // If not
             storage += amount;
             System.out.println("Put: " + amount + ", Total: " + storage);
             Thread.sleep(1000);
             // Notify that it is ready to get.
             flag = true;
             // awaken get thread.
             notify();
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
    }

    public synchronized void get(int amount) {
         try {
             // If there is enough to get and it is put's turn.
             while (amount > storage || !flag) {
                 System.out.println("Want to get: " + amount);
                 // enable put thread
                 flag = false;
                 // awaken put thread
                 notify();
                 // wait until put thread notify()
                 wait();
             }
             storage -= amount;
             System.out.println("Get: " + amount + ", total: " + storage);
             Thread.sleep(1000);
             // Notify put that get has finished
             flag = false;
             notify();
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
    }

    public int getStorage() {
         return storage;
    }
}
 
     生产者:
package producerConsumer;

import java.util.Random;

public class Producer implements Runnable{
    Storage s;

    public Producer(Storage s) {
         // TODO Auto-generated constructor stub
         this.s = s;
         new Thread(this, "producer").start();
    }

    @Override
    public void run() {
         // TODO Auto-generated method stub
         while (true) {
             s.put((new Random()).nextInt(10));
         }
    }
}

     消费者:
package producerConsumer;

import java.util.Random;

public class Consumer implements Runnable {
    Storage s;

    public Consumer(Storage s) {
         // TODO Auto-generated constructor stub
         this.s = s;
         new Thread(this, "consumer").start();
    }

    @Override
    public void run() {
         // TODO Auto-generated method stub
         while (true) {
             s.get((new Random()).nextInt(20));
         }
    }
}

     主函数:
package producerConsumer;

public class PCTest {

    public static void main(String[] args) {
         // TODO Auto-generated method stub
         Storage storage = new Storage();
         new Producer(storage);
         new Consumer(storage);
    }

}
     

当然,除了这种方法实现生产者/消费者问题之外,使用之前提到的三种方法也是可以实现的,只不过不能使得进程一直等待,所以要把put和get函数中的while(true)循环删除或者变成if判断,以免线程阻塞。
0 0