线程

2018-09-24  本文已影响0人  咔狼

Thread

线程的使用方法

方法1
class Demo extends Thread{
    @Override
    public void run(){
        // 任务
    }
}

Demo d1 = new Demo();
// 启动线程
d2.start();
方法2(推荐)
class Demo2 implements Runnable{
    @Override
    public void run() {
        // 任务
    }
}

Demo2 d = new Demo2();
// 创建Thread类对象,将Runnable接口的子类对象作为参数传递给thread类的构造方法
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
// 启动线程
t1.start();
t2.start();

线程的运行安全

线程的运行流程
同步代码块
Object obj = new Object();
public void run(){
    while(true){
        synchronized(obj){
            //需要同步的代码
        }
    }
}
同步方法
public synchronized void sale(){
    //需要同步的代码
}
线程常用方法

sleep()强迫一个线程睡眠N毫秒
join()等待线程终止
currentThread()得到当前线程(拿到当前方法所在的线程对象)
isDaemon()一个线程是否为守护线程
setDaemon()设置一个线程为守护线程
setName()为线程设置一个名称
wait()强迫一个线程等待
notify()通知一个线程继续运行
setPriority()设置一个线程的优先级

单例模式线程安全

多线程操作单例模式(延迟加载方式)时所发生的问题:

栗子1 -- 无线程安全问题

class Single {
    private Single() {}
    private static final Single s = new Single();
    public static Single getInstance() {
        return s;
    }
}

栗子2 -- 延迟加载方式线程安全问题解决方案

class Single2 {
    private Single2() {}
    private static final Single s2 = null;
    public static Single getInstance() {
        if (s2 == null) {
            synchronized (Single2.class) {
                if (s2 == null) {
                    s2 = new Single2();
                }
            }
        }
        return s2;
    }
}
接口Lock与监视器对象(Condition)

监视器方法:
await()线程进入等待
signal()随机唤醒一个等待线程
signalAll()唤醒所有等待线程

Lock与Condition代码实例 -- 生产者与消费者问题

class Resource {
    private String name;
    private int count = 1;
    private boolean flag = false;
    // 定义一个锁对象
    private Lock lock = new ReentrantLock();
    // 获取锁上的Condition对象
    // 为了解决本方唤醒对方问题, 可以一个锁创建两个监视器对象
    private Condition producer = lock.newCondition();// 生产
    private Condition consumer = lock.newCondition();// 消费
    public void set(String name) {
        // 获取锁
        lock.lock();
        try {
            // 随机抽取线程进入锁, while判断标记为false则执行生产代码, 如果为true则等待
            while (flag) {
                try {
                    producer.await();
                } catch (InterruptedException e) {
                    e.printStackTrance();
                }
                this.name = name + count;
                count ++;
                System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);// 生产商品
                flag = true;
                // 执行消费线程的唤醒, 随机唤醒一个消费线程释放锁
                consumer.signal();
            }
        } finally {
            lock.unlock;
        }
    }
    public void out() {
        lock.lock();
        try {
            // 随机抽取线程进入锁, while判断标记为false则执行生产代码, 如果为true则等待
            while (!flag) {
                try {
                    consumer.await();
                } catch (InterruptedException e) {
                    e.printStackTrance();
                }
                System.out.println(Thread.currentThread().getName() + "..消费者.." + this.name);// 消费商品
                // 标记修改为false
                flag = false;
                // 随机唤醒一个生产线程释放锁
                producer.signal();
            }
        } finally {
            lock.unlock;
        }
    }
}
sleep()与wait()的区别

相同点:

不同点:

  1. sleep必须指定时间,wait可以指定也可以不指定时间
  2. sleep时间一到,线程处于临时阻塞状态或运行状态,wait如果没有指定的时间,必须要通过notify或者notifyAll唤醒
  3. sleep不一定非要定义在同步中,wait必须要定义在同步中
  4. 都定义在同步中时,线程执行到sleep不会释放锁,而线程执行到wait会释放锁

线程的细节

停止线程
守护线程
线程的优先级
类型 字段 注释
static int MAX_PRIORITY 线程可以具有的最高优先级----优先级范围(10)
static int MIN_PRIORITY 线程可以具有的最低优先级----优先级范围(5)
static int NORM_PRIORITY 分配给线程的默认优先级----优先级范围(0)
等待线程终止

join()等待该线程终止

线程临时暂停

Thread.yield()临时停止当前正在运行的线程,让另外的线程执行

匿名线程

使用匿名内部类创建匿名线程以及实现Runnable接口
一个栗子

// 匿名内部类
new Thread() {
    @Override
    public void run() {
        // 任务
    }
}.start();
// 实现Runable接口创建线程
Runnable r = new Runnable() {
    @Override
    public void run() {
        // 任务
    }
};
new Thread(r).start();
上一篇 下一篇

猜你喜欢

热点阅读