zoukankan      html  css  js  c++  java
  • Java多线程

    标签 :java基础


    1. Java多线程的实现

    (1)继承Thread类,重写run方法。
    (2)实现Runnable接口,重写run方法。(这个设计比较好)
    本质上Thread类就是实现了Runable的类。

    // 创建线程
    Runnable task = new TaskClass();
    // 开启线程
    new Thread(task).start();
    

    2. 线程池使用

    使用ExecutorService类和Executors类实现线程池,代码如下:

    // 固定线程数的线程池
    ExecutorService executor = Executors.newFixedThreadPool(3);
    // 按需创建新线程的线程池
    ExecutorService executor2 = Executors.newCachedThreadPool();
    // 使用线程池
    executor.execute(new TaskClass());
    // 关闭线程池
    executor.shutdown();
    

    3. 线程同步问题

    (1)竞争状态问题:多个线程以冲突的方式访问一个公共资源
    (2)线程安全的类:该类的对象在多线程下没有导致竞争状态问题。
    线程安全、不安全的类就是指这种公共资源类

    4. 解决线程同步问题

    (1)给临界区方法加synchonized关键字。
      一个线程访问这个方法时,整个对象锁住,其他线程访问这个对象的任意方法会阻塞,直到解锁。
    (2)给需要同步的语句包上synchronized语句块。
      好处是只需要锁住导致线程不安全的语句,而不是锁住整个方法。

    synchronized(obj){
        doSomething();
    }
    

    (3)显式使用锁。
      实现了Lock接口的对象是一个锁对象。可以利用锁对象对其他对象显式加锁。例如ReentrantLock类,可以创建具有公平策略的锁,即那个线程先来那个先得。(默认不是公平锁)
      使用方法,在需要实现同步访问的类中,组合一个Lock接口的实例,在临界区前调用lock.lock(),在结束后调用lock.unlock()。如下:

    public void add(int a){
        lock.lock();
        try{
            // 临界区
            doSomething();
        }
        catch(InterruptedException e){
        }
        finally{
            lock.unlock();
        }
        // 写try-catch这个习惯比较好,保证锁能释放
    }
    

      ReentrantLock类可以创建condition,比synchronzied关键字更灵活可控。
     

    5. 线程间合作

    (1)使用Condition接口的实例。Condition接口的实例从Lock对象生成,使用时必须获得该Condition的锁(否则抛出异常)。使用方法是把Condition的实例放在Lock实例的他同一个类底下。

    // 创建条件
    private static Condition condition = lock.newCondition();
    // 阻塞当前线程,直到别人来唤醒
    condition.await();
    // 唤醒所有阻塞线程
    condtition.signalAll();
    

    (2)传统方法,监视器。即使用每个对象本身的wait(),notify(),notifyAll()等方法。

    6. 生产者/消费者模型

    (1)使用一个lock,两个condition(notEmpty和notFull),每次生产/消费时用lock锁住Buffer。
    (2)如果生产时发现容器已满,需要等待notFull条件;
    (3)同样,如果消费时发现容器为空,则需要等待notEmpty条件。
    (4)每次生产完唤醒等待notEmpty条件的线程,每次消费完唤醒等待notFull条件的线程。

  • 相关阅读:
    PEM_密钥对生成与读取方法
    RandomStringUtils RandomUtils
    Java高级个人笔记(RandomStringUtils工具类)
    如何让eclipse输出结果的console栏自动换行?
    日志框架logj的使用
    IDEA中Git的更新、提交、还原方法
    AWS核心服务概览
    技术资料的几种读法
    李笑来老师在《把时间当作朋友》曾说过:“所有学习上的成功,都只靠两件事:策略和坚持,而坚持本身就应该是最重要的策略之一
    ubuntu如何修改terminal终端的主机名(修改/etc/hostname文件)
  • 原文地址:https://www.cnblogs.com/banyu/p/6690982.html
Copyright © 2011-2022 走看看