多线程习题

  1. 三个线程t1、t2、t3。确保三个线程,t1执行完后t2执行,t2执行完后t3执行。
使用Semaphore
  1. 三个线程t1、t2、t3。确保三个线程,t1,t2执行完,t3再执行。
public class Test01 {

    private Object obj = new Object();
	
    //线程1、2执行完后,再执行线程3,使用wait()、notify()
    public static void main(String[] args) {
        new Test01().exec();
    }

    public void exec(){
        new Thread(()->{
            synchronized (obj){
                try {
                    obj.wait();
                    System.out.println("线程:"+Thread.currentThread().getName()+"=>执行了....");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },String.valueOf(3)).start();

        for (int i = 0; i < 2; i++) {
            final int tmp = i;
            new Thread(()->{
                synchronized (obj){
                    System.out.println("线程:" + Thread.currentThread().getName() + "=>执行了....");
                    if(tmp == 1)
                        obj.notify();
                }
            },String.valueOf(i+1)).start();
        }
    }
}
public class Test02 {

    private CountDownLatch latch =new CountDownLatch(2);

    //线程1、2执行完后,再执行线程3,使用CountDownLatch
    public static void main(String[] args) {
        new Test02().exec();
    }

    public void exec(){
        new Thread(()->{
            try {
                latch.await();
                System.out.println(Thread.currentThread().getName() + "=>执行了....");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"线程3").start();

        for (int i = 0; i < 2; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "=>执行了....");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            },String.valueOf("线程" + (i+1))).start();
        }
    }
}
class T1 implements Runnable{

	@Override
	public void run() {
		System.out.println("1");
	}	
}

class T2 implements Runnable{

	Thread father;
	
	public void set(Thread father) {
		this.father = father;
	}
	
	@Override
	public void run() {
		try {
			father.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("2");
	}
}

class T3 implements Runnable{

	Thread father;
	
	public void set(Thread father) {
		this.father = father;
	}
	
	@Override
	public void run() {
		try {
			father.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("3");
	}
}

public class Test {
	//使用join
	public static void main(String[] args) {
		T1 task1 = new T1();
		T2 task2 = new T2();
		T3 task3 = new T3();
		
		Thread t1 = new Thread(task1);
		Thread t2 = new Thread(task2);
		Thread t3 = new Thread(task3);
		
		task2.set(t1);
		task3.set(t1);
		
		t1.start();
		t2.start();
		t3.start();
	}
}
  1. 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象。
public class Test {

    /**
     * 现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,
     * 请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日志对象;
     * 思路1:
     *      1.将16个日志对象放到阻塞队列中
     *      2.开启4个线程从阻塞队列中拿日志对象执行
     *      3.日志对象执行时间为 1s
     *      4.此方式线程会一直跑,阻塞
     *
     * 思路2:
     *      1.创建具有4个核心线程的线程池
     *      2.在阻塞队列中加入16个打印日志对象的任务
     *      3.执行线程池的任务
     *      4.日志对象执行时间为 1s
     *      5.此方式线程会销毁
     *
     */
    public static void main(String[] args) {
        test01();   //思路1实现
        //test02();   //思路2实现
    }

    private static void test01() {
        long start = System.currentTimeMillis();
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);

        //将16个日志对象放入阻塞队列中
        for (int i = 1; i <= 16; i++) {
            try {
                queue.put("日志对象:" + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //开启4个线程从阻塞队列中拿日志对象执行
        for (int i = 0; i < 4; i++) {
            new Thread(()->{
                while(true){
                    try {
                        String log = queue.take();
                        printLog(log);
                        long end = System.currentTimeMillis();
                        System.out.println((end-start) + "ms");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }


    public static void test02(){
        long start = System.currentTimeMillis();
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(16);

        //创建具有四个核心线程的线程池
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                4,
                4,
                3000,
                TimeUnit.MILLISECONDS,
                queue,
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        //将16个打印日志对象的任务放入阻塞队列中
        for (int i = 0; i < 16; i++) {
            final String tmp = "任务" + (i+1) + "";
            poolExecutor.execute(()->{
                printLog(tmp);
            });
        }
        poolExecutor.shutdown();

        //判断线程池的任务是否执行完毕
        while(true){
            long end = System.currentTimeMillis();
            if(poolExecutor.isTerminated()){
                System.out.println((end-start) + "ms");
                break;
            }
        }
    }

    public static void printLog(String log){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "===>打印日志=========>" + log);
    }

}
  1. 10个线程同步执行10个任务
public class Test2 {

    /**
     * 10个线程同步执行10个任务
     * 方式1:synchronized
     * 方式2:Lock
     * 方式3:Semaphore
     * @param args
     */
    public static void main(String[] args) {
        //test01();   //synchronized
        //test02();   //Lock
        test03();     //Semaphore
    }


    public static void test01(){
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
        //往阻塞队列中加入任务
        for (int i = 0; i < 10; i++) {
            try {
                queue.put("任务:" + (i+1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //10个线程顺序执行任务
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                synchronized (queue){
                    try {
                        String task = queue.take();
                        executeTask(task);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    public static void test02(){
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
        Lock lock = new ReentrantLock();
        //往阻塞队列中加入任务
        for (int i = 0; i < 10; i++) {
            try {
                queue.put("任务:" + (i+1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //10个线程顺序执行任务
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    lock.lock();
                    String task = queue.take();
                    executeTask(task);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }).start();
        }
    }

    public static void test03(){
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
        Semaphore semaphore = new Semaphore(1);
        //往阻塞队列中加入任务
        for (int i = 0; i < 10; i++) {
            try {
                queue.put("任务:" + (i+1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //10个线程顺序执行任务
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();
                    String task = queue.take();
                    executeTask(task);
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

    }

    public static void executeTask(String task){
        System.out.println(Thread.currentThread().getName() + "==>" + task);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  1. 10个商品被20个用户抢购,如何让商品正常卖出,不会超卖:
public class Test03 {

    //10个商品
    private int goods = 10;
    
    public static void main(String[] args) {
        new Test03().exec();
    }

    public synchronized void exec(){
        for (int i = 0; i < 20; i++) {
            new Thread(()->{
                if(goods > 0){
                    System.out.println(Thread.currentThread().getName() + ",抢到了第 " + goods-- + " 张票");
                }
            },String.valueOf("用户" + (i+1))).start();
        }
    }
}
  1. 生产者消费者问题
//数据
class Data{
	
	private String message;
	
	public String getMessage() {
		return message;
	}
	
	public void setMessage(String message) {
		this.message = message;
	}
}


//生产者
class Producer implements Runnable{

	private Data data;
	
	public Producer(Data data) {
		this.data = data;
	}
	
	@Override
	public void run() {
		int i = 0;
		while(true) {
			synchronized(data){
				//如果数据为空,则生产数据
				if(data.getMessage() == null) {
					data.setMessage(i + "");
					System.out.println("生产:" + i);
					i++;
				}
				//生产完数据通知消费者消费
				data.notify();
				//生产者挂起
				try {
					data.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

//消费者
class Consumer implements Runnable{
	private Data data;
	
	public Consumer(Data data) {
		this.data = data;
	}
	
	public void run() {
		while(true) {
			synchronized(data) {
				//如果数据不为空,则消费
				if(data.getMessage() != null) {
					System.out.println("消费:" + data.getMessage());
					data.setMessage(null);
				}
				//消费完,通知生产者进行生产
				data.notify();
				//消费者挂起
				try {
					data.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

}


public class Test {
	
	public static void main(String[] args) {
		Data data = new Data();
		Producer p = new Producer(data);
		Consumer c = new Consumer(data);
		
		Thread t1 = new Thread(p);
		Thread t2 = new Thread(c);
		
		t1.start();
		t2.start();
	}
}
  1. 优雅的停止线程
class Task implements Runnable{
	
	private volatile boolean isFlag = true;
	
	public void stop() {
		this.isFlag = false;
	}
	
	public void run() {
		int i = 0;
		while(isFlag) {
			System.out.println(i++);
		}
	}
}

public class Test {
	//使用标志位
	public static void main(String[] args) throws InterruptedException {
		Task task = new Task();
		Thread t = new Thread(task);
		t.start();
		TimeUnit.SECONDS.sleep(1);
		task.stop();
	}
}
class Task implements Runnable{
	
	public void run() {
		int i = 0;
		while(true) {
			Thread t = Thread.currentThread();
			if(t.isInterrupted()) {  //判断是否处于中断状态
				break;
			}
			System.out.println(i++);
		}
	}
}

public class Test {
	//使用interrupt
	public static void main(String[] args) throws InterruptedException {
		Task task = new Task();
		Thread t = new Thread(task);
		t.start();
		TimeUnit.SECONDS.sleep(1);
		t.interrupt();  //中断
	}
}
  1. 多线程循环顺序打印:ABABABABAB,线程A打印A,线程B打印B。
使用Object.wait()和notifyAll()  或者Lock + Condition
  1. 多线程循环顺序打印:0102030405,线程0打印0,线程1打印奇数,线程2打印偶数
使用Object.wait()和notifyAll()  或者Lock + Condition

代码后续更新。。。


shutdown和shutwdown的区别:

  • shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。
  • shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。

isShutDown:

  • isShutDown当调用shutdown()或shutdownNow()方法后返回为true。
  • isTerminated当调用shutdown()方法后,并且所有提交的任务完成后返回为true;
  • isTerminated当调用shutdownNow()方法后,成功停止后返回为true;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值