Skip to content

Latest commit

 

History

History
416 lines (361 loc) · 12.2 KB

多线程编程题.md

File metadata and controls

416 lines (361 loc) · 12.2 KB

一个多线程的问题,用三个线程,顺序打印字母A-Z,输出结果是1A 2B 3C 1D 2E…打印完毕最后输出一个Ok。

public class Test {
    private static char c = 'A';
    private static int i = 0;

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    try {
                        int id = Integer.parseInt(Thread.currentThread().getName());
                        while (i < 26) {
                            if (i % 3 == id - 1) {
                                System.out.println("线程id:" + id + " " + (char) c++);
                                i++;
                                notifyAll();
                            } else {
                                wait();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        new Thread(r, "1").start();
        new Thread(r, "2").start();
        new Thread(r, "3").start();
    }
}

每个线程把自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示

LockSupport

public class Main {
    static Thread threadA, threadB, threadC;
    public static void main(String[] args) {
        threadA = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.print(Thread.currentThread().getName());
                LockSupport.unpark(threadB);
                LockSupport.park();
            }
        }, "A");

        threadB = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.print(Thread.currentThread().getName());
                LockSupport.unpark(threadC);
                LockSupport.park();
            }
        }, "B");

        threadC = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.print(Thread.currentThread().getName());
                LockSupport.unpark(threadA);
                LockSupport.park();
            }
        }, "C");

        threadA.start();
        threadB.start();
        threadC.start();
    }
}

ReentrantLock

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition conA = lock.newCondition();
        Condition conB = lock.newCondition();
        Condition conC = lock.newCondition();

        // A
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < 10; i++) {
                    System.out.print(Thread.currentThread().getName());
                    conB.signal();
                    conA.await();
                }
                conB.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "A").start();

        // B
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < 10; i++) {
                    System.out.print(Thread.currentThread().getName());
                    conC.signal();
                    conB.await();
                }
                conC.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "B").start();

        // C
        new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < 10; i++) {
                    System.out.print(Thread.currentThread().getName());
                    conA.signal();
                    conC.await();
                }
                conA.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "C").start();
    }
}

两线程奇偶数打印

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    static int value = 0;
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition conA = lock.newCondition();
        Condition conB = lock.newCondition();
        // A
        new Thread(() -> {
            try {
                lock.lock();
                while (value <= 100) {
                    System.out.println(Thread.currentThread().getName() + " " + value++);
                    conB.signal();
                    conA.await();
                }
                conB.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "A").start();

        // B
        new Thread(() -> {
            try {
                lock.lock();
                while (value <= 100) {
                    System.out.println(Thread.currentThread().getName() + " " + value++);
                    conA.signal();
                    conB.await();
                }
                conA.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "B").start();

    }
}

启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10。直到75

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    static int value = 1;
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition conA = lock.newCondition();
        Condition conB = lock.newCondition();
        // A
        new Thread(() -> {
            try {
                lock.lock();
                while (value <= 75) {
                    System.out.print(Thread.currentThread().getName() + " ");
                    for (int i = 0; i < 5; i++) {
                        System.out.print(value++ + " ");
                    }
                    System.out.println("");
                    conB.signal();
                    conA.await();
                }
                conB.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "A").start();

        // B
        new Thread(() -> {
            try {
                lock.lock();
                while (value <= 75) {
                    System.out.print(Thread.currentThread().getName() + " ");
                    for (int i = 0; i < 5; i++) {
                        System.out.print(value++ + " ");
                    }
                    System.out.println("");
                    conA.signal();
                    conB.await();
                }
                conA.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "B").start();

    }
}

如何确保三个线程顺序执行?

join

public class ThreadTest1 {
// T1、T2、T3三个线程顺序执行
public static void main(String[] args) {
    Thread t1 = new Thread(new Work(null));
    Thread t2 = new Thread(new Work(t1));
    Thread t3 = new Thread(new Work(t2));
    t1.start();
    t2.start();
    t3.start();
 
}
static class Work implements Runnable {
    private Thread beforeThread;
    public Work(Thread beforeThread) {
        this.beforeThread = beforeThread;
    }
    public void run() {
        if (beforeThread != null) {
            try {
                beforeThread.join();
                System.out.println("thread start:" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("thread start:" + Thread.currentThread().getName());
        }
    }
 }
}

CountDownLatch

public class ThreadTest2 {
 
// T1、T2、T3三个线程顺序执行
public static void main(String[] args) {
    CountDownLatch c0 = new CountDownLatch(0); //计数器为0
    CountDownLatch c1 = new CountDownLatch(1); //计数器为1
    CountDownLatch c2 = new CountDownLatch(1); //计数器为1
 
    Thread t1 = new Thread(new Work(c0, c1));
    //c0为0,t1可以执行。t1的计数器减1
 
    Thread t2 = new Thread(new Work(c1, c2));
    //t1的计数器为0时,t2才能执行。t2的计数器c2减1
 
    Thread t3 = new Thread(new Work(c2, c2));
    //t2的计数器c2为0时,t3才能执行
 
    t1.start();
    t2.start();
    t3.start();
 
}
 
//定义Work线程类,需要传入开始和结束的CountDownLatch参数
static class Work implements Runnable {
    CountDownLatch c1;
    CountDownLatch c2;
 
    Work(CountDownLatch c1, CountDownLatch c2) {
        super();
        this.c1 = c1;
        this.c2 = c2;
    }
 
    public void run() {
        try {
            c1.await();//前一线程为0才可以执行
            System.out.println("thread start:" + Thread.currentThread().getName());
            c2.countDown();//本线程计数器减少
        } catch (InterruptedException e) {
        }
 
    }
 }
}

blockingQueue

public class ThreadTest4 {
// T1、T2、T3三个线程顺序执行
public static void main(String[] args) {
    //blockingQueue保证顺序
    BlockingQueue<Thread> blockingQueue = new LinkedBlockingQueue<Thread>();
    Thread t1 = new Thread(new Work());
    Thread t2 = new Thread(new Work());
    Thread t3 = new Thread(new Work());
 
    blockingQueue.add(t1);
    blockingQueue.add(t2);
    blockingQueue.add(t3);
 
    for (int i=0;i<3;i++) {
        Thread t = null;
        try {
            t = blockingQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.start();
        //检测线程是否还活着
        while (t.isAlive());
    }
}
 
static class Work implements Runnable {
 
    public void run() {
        System.out.println("thread start:" + Thread.currentThread().getName());
    }
 }
}

CachedThreadPool

 public class ThreadTest3 {
    // T1、T2、T3三个线程顺序执行
   public static void main(String[] args) {
    FutureTask<Integer> future1= new FutureTask<Integer>(new Work(null));
    Thread t1 = new Thread(future1);
 
    FutureTask<Integer> future2= new FutureTask<Integer>(new Work(future1));
    Thread t2 = new Thread(future2);
 
    FutureTask<Integer> future3= new FutureTask<Integer>(new Work(future2));
    Thread t3 = new Thread(future3);
 
    t1.start();
    t2.start();
    t3.start();
}
 
 static class Work  implements Callable<Integer> {
    private FutureTask<Integer> beforeFutureTask;
    public Work(FutureTask<Integer> beforeFutureTask) {
        this.beforeFutureTask = beforeFutureTask;
    }
    public Integer call() throws Exception {
        if (beforeFutureTask != null) {
            Integer result = beforeFutureTask.get();//阻塞等待
            System.out.println("thread start:" + Thread.currentThread().getName());
        } else {
            System.out.println("thread start:" + Thread.currentThread().getName());
        }
        return 0;
    }
 } 
}

https://blog.csdn.net/Evankaka/article/details/80800081