多线程复习(一)

新建线程的方法有三种
1、继承Thread类
2、继承runnable接口
3、继承callable

执行线程的方法有两种
1、Thread.start();
2、ExcuteService.excute(new Thread);

线程的五种状态:
1、新建
2、就绪
3、运行
4、阻塞
5、结束

Thread类:

    run()和start()要注意一下,run意味着在当前线程执行了实例的某个方法,start意味着开启线程,仅仅是run()的话是没有并行工作的效应的。
    yield()暂停线程,不能指定时间,仅仅是可以让同优先级的线程先执行。sleep()线程睡眠可以指定睡眠多少时间,可以让其他线程获得执行,但是不释放锁,信息依然不共享。
    join()等待线程结束,如果在ThreadA中调用threadB.join()则ThreadA的thread.join()后面的程序要等到threadB结束后才运行。是fork-join的主要实现方法。
    get/setPriority()设置优先级

线程同步:

    关键字synchronizd,如果某个static方法要锁,则给整个类加锁,如果是给某个对象实例的某个代码块加锁,则给对象加锁。
    感觉最重要的:显示加锁以下给出书上的消费生产者实例
public class threadTest {
    private static Buffer buffer = new Buffer();


    public static void main(String[] args) {
        /*建立线程池
        * 线程池用于管理并发执行任务个数的方法
        * newFixed池如果任务超过规定的上线,则新的线程等待之前的任务执行完毕*/
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(new ProducerTask());
        executorService.execute(new ConsumerTask());
        executorService.shutdown();
    }
    static class ProducerTask implements Runnable{

        @Override
        public void run() {
            try {
                int i=1;
                while (true){
                    System.out.println("Producer writes "+i);
                    buffer.write(i++);
                    Thread.sleep((int)(Math.random()*10000));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class ConsumerTask implements Runnable{

        @Override
        public void run() {
            try {
                while (true){
                    System.out.println("\t\t\tConsumer reads"+buffer.read());
                    Thread.sleep((int)(Math.random()*10000));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class Buffer{
        //定义buffer的大小
        private static final int CAPACITY = 1;
        private LinkedList<Integer> queue = new LinkedList<>();
        //创建一个新lock
        private static Lock lock = new ReentrantLock();
        private static Condition notEmpty = lock.newCondition();
        private static Condition notFull = lock.newCondition();

        public void write(int value){
            lock.lock();
            try {
                while (queue.size()==CAPACITY){
                    //队列已满等待未满的信号来进行解锁进行下一步插入操作
                    System.out.println("Wait for notFull condition to insert");
                    notFull.await();
                }

                queue.offer(value);
                //当前队列非空,释放当前队列非空信号,使下面的read操作可以执行下去
                notEmpty.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            finally {
                lock.unlock();
            }
        }
        public int read(){
            int value = 0;
            lock.lock();
            try {
                while (queue.isEmpty()){
                    System.out.println("\t\twait for notEmpty condition");
                    notEmpty.await();
                }
                value = queue.remove();
                notFull.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            finally {
                lock.unlock();
                return value;
            }
        }

    }
}

lock和condition:

    lock是锁住代码块的锁,condition是从lock中获取的标识,个人暂时理解为程序阻塞点的标识。
    condition有如下方法:await()让程序阻塞,signal()唤醒同一个condition实例阻塞的程序,signalAll()唤醒同一个lock的所有condition实例。

Object的线程方法:

    wait,notify,notifyAll,Object自带的原生方法,这些方法必须在实例的同步方法或者同步代码块中调用,具体效果类似于condition里面的wait和signal

死锁:

如下`thread1
synchronized(object1){
        synchronized(object2){

        }       
thread2

synchronized(object2){
        synchronized(object1){
        }
    }
    即两个线程互相等待对方的锁。
    避免死锁的方式:采用正确的资源排序避免死锁.
发布了43 篇原创文章 · 获赞 1 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章