您的位置 首页 java

Java多线程–线程常见方法

  1. sleep(Thread类方法)
  • 当调用 Thread.sleep(long millis) 睡眠方法时,就会使当前线程进入阻塞状态;当时间结束之后,线程会重新进入就绪状态;
  • 如果当前线程获得了一把同步锁,则 sleep方法阻塞期间,是不会释放锁的;
  1. join(Thread类方法)
  • 当A线程调用B线程的join方法时,A就会进入阻塞状态;直到B线程执行完毕,A才会由阻塞状态转为就绪状态;代码示例:t1、t2、t3三个线程顺序执行:
 public class TestJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MultiT("a"));
        Thread t2 = new Thread(new MultiT("b"));
        Thread t3 = new Thread(new MultiT("c"));
        
        t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
        t3.join();
   }
}
class MultiT implements Runnable{
    private String s;
    private int i;
    public MultiT(String s){
        this.s = s;
   }
    @ Override 
    public void run() {
        while(i<10){
            System.out.println(s+"===="+i++);
       }
   }
}  
  1. yield(Thread类方法)
  • Thread.yield 方法会使当前线程放弃CPU时间片,把执行机会让给相同或更高优先级的线程;
  • 此时当前线程不会阻塞,只是进入了就绪状态,随时可以再次获得CPU时间片,从而进入运行状态;
  • yield方法,并不能保证,其它相同或更高优先级的线程一定会获得执行权,也有可能,再次被当前线程拿到执行权;
  • yeild方法与sleep一样,不会释放锁资源;代码示例: 既然yield不释放锁,那为什么还要放弃执行权呢。就算放弃了执行权,别的线程也无法获得锁啊
 public class TestYield {
    public static void main(String[] args) {
        YieldThread yieldThread = new YieldThread();
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(yieldThread);
            t.start();
       }
   }
}

class YieldThread implements Runnable {
    private int count = 0;
    @Override
    public  synchronized  void run() {
        for (int i = 0; i < 10; i++) {
            count ++;
            if(count == 1){
                Thread.yield();
                System.out.println("线程:"+Thread.currentThread().getName() + "让步");
           }
            System.out.println("线程:"+Thread.currentThread().getName() + ",count:"+count);
       }
   }
}

结果:
线程:Thread-0让步
线程:Thread-0,count:1
线程:Thread-0,count:2
线程:Thread-0,count:3    
线程:Thread-0,count:4    
线程:Thread-0,count:5    
线程:Thread-0,count:6    
线程:Thread-0,count:7    
线程:Thread-0,count:8    
线程:Thread-0,count:9    
线程:Thread-0,count:10
线程:Thread-0,count:11   
线程:Thread-0,count:12    
  1. wait、notify、notifyAll(Object的方法)
  • 调用线程的wait方法会使当前线程等待,直到其它线程调用此对象的notify/notifyAll方法;
  • 当前对象锁有N个线程在等待,则notify方法会随机唤醒其中一个线程,而notifyAll会唤醒对象锁中所有的线程;
  • 注意,需要配合 synchronized关键字来使用,唤醒时,不会立马释放锁,只有当前线程执行完之后,才会把锁释放;生产者和消费者示例:
 //商店类(Shop):定义一个成员变量,表示第几个面包,提供生产面包和消费面包的操作
public class Shop {
    private int bread = 0;
    private final int MAX_NUM = 5;
    private Object synObj = new Object();
    //生产面包
    public void produceBread() {
        synchronized(synObj){
           while (bread == MAX_NUM) {
                System.out.println(Thread.currentThread().getName() + ":已经生产完" + bread + "个面包");
                synObj.wait(); //到达生产上限,等待其他线程消费
            }
            bread++;
            System.out.println(Thread.currentThread().getName() + ":开始生产第" + bread + "个面包");
            synObj.notifyAll(); // 唤醒所有消费者线程 
        }
        
    }
    
    //消费面包
    public void consumeBread() {
        synchronized(synObj){
        while (bread == 0) {
                System.out.println(Thread.currentThread().getName() + ":已经消费完,剩余" + bread + "个面包");
                synObj.wait(); //已经消费完面包,等待其他线程生产
            }
            bread--;
            System.out.println(Thread.currentThread().getName() + ":开始消费,剩余" + bread + "个面包");
            synObj.notifyAll(); // 唤醒所有生产者线程
        }
    }
}

//生产者类(Producer):实现 Runnable 接口,重写 run() 方法,调用生产面包的操作
public class Producer extends Thread {
    private Shop shop;
    public Producer(Shop shop) {
        this.shop = shop;
    }
    
    @Override
    public void run() {
        System.out.println(getName() + ":开始生产面包.....");
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            shop.produceBread();
        }
    }
}
//消费者类( Consumer ):实现 Runnable 接口,重写 run() 方法,调用消费面包的操作
public class Consumer extends Thread {
    private Shop shop;
    public Consumer(Shop shop) {
        this.shop = shop;
    }
    
    @Override
    public void run() {
        System.out.println(getName() + ":开始消费面包.....");
        while (true) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            shop.consumeBread();
        }
    }
}  
  1. awiat、signal、signalAll(juc包中的 condition 类)
  • 作用同上,一般配合 lock 使用;消费者和生产者示例:
 //商店类(Shop):定义一个成员变量,表示第几个面包,提供生产面包和消费面包的操作
public class Shop {
    private int bread = 0;
    private final int MAX_NUM = 5;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    //生产面包
    public void produceBread() {
        lock.lock();
        try{
            while (bread == MAX_NUM) {
                System.out.println(Thread.currentThread().getName() + ":已经生产完" + bread + "个面包");
                condtion.await(); //到达生产上限,等待其他线程消费
           }
            bread++;
            System.out.println(Thread.currentThread().getName() + ":开始生产第" + bread + "个面包");
            condition.signalAll(); // 唤醒所有消费者线程
       }
        catch(InterruptedException e){
            e.printStackTrace();
       } 
        finally{
            lock.unlock();
       }   
   }
    
    //消费面包
    public synchronized void consumeBread() {
        lock.lock();
        try{
            while (bread == 0) {
                System.out.println(Thread.currentThread().getName() + ":已经消费完,剩余" + bread + "个面包");
                condition.await(); //已经消费完面包,等待其他线程生产
           }
            bread--;
            System.out.println(Thread.currentThread().getName() + ":开始消费,剩余" + bread + "个面包");
            condition.signalAll(); // 唤醒所有生产者线程
       }
        catch(InterruptedException e){
            e.printStackTrace();
       } 
        finally{
            lock.unlock();
       }
   }
}

//生产者类(Producer):实现 Runnable 接口,重写 run() 方法,调用生产面包的操作
public class Producer extends Thread {
    private Shop shop;
    public Producer(Shop shop) {
        this.shop = shop;
   }
    
    @Override
    public void run() {
        System.out.println(getName() + ":开始生产面包.....");
        while (true) {
            try {
                Thread.sleep(100);
           } catch (InterruptedException e) {
                e.printStackTrace();
           }
            shop.produceBread();
       }
   }
}
//消费者类(Consumer):实现 Runnable 接口,重写 run() 方法,调用消费面包的操作
public class Consumer extends Thread {
    private Shop shop;
    public Consumer(Shop shop) {
        this.shop = shop;
   }
    
    @Override
    public void run() {
        System.out.println(getName() + ":开始消费面包.....");
        while (true) {
            try {
                Thread.sleep(500);
           } catch (InterruptedException e) {
                e.printStackTrace();
           }
            shop.consumeBread();
       }
   }
}  

文章来源:智云一二三科技

文章标题:Java多线程–线程常见方法

文章地址:https://www.zhihuclub.com/200127.shtml

关于作者: 智云科技

热门文章

发表回复

您的电子邮箱地址不会被公开。

网站地图