Java多线程经典编程题
1. 要求线程a执行完才开始线程b, 线程b执行完才开始线程
package com.example.javatest.theardTest.MultiThreadAlgorithm;
/**
*/
public class T1T2T3 {
| public static class PrintThread extends Thread{ |
| |
| PrintThread(String name){ |
| super(name); |
| } |
| |
| @Override |
| public void run() { |
| for(int i = 0; i < 100; i++){ |
| System.out.println(getName() + " : " + i); |
| } |
| } |
| } |
| |
| public static void main(String[] args){ |
| |
| PrintThread t1 = new PrintThread("a"); |
| PrintThread t2 = new PrintThread("b"); |
| PrintThread t3 = new PrintThread("c"); |
| |
| try { |
| |
| t1.start(); |
| t1.join(); |
| |
| t2.start(); |
| t2.join(); |
| |
| t3.start(); |
| t3.join(); |
| |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| |
| |
| } |
}
/**
- 我对于join方法的理解:
- join() 的源码:
- public final void join(long millis) throws InterruptedException {
-
-
-
-
-
-
-
- }
- 其实就是main()线程调用join()后,synchronized(lock)语句块,获得lock的锁,
- 然后判断如果t1线程isAlive(), 就一直lock.wait(), 让自己(main()线程)阻塞住,
- 直到t1线程 !isAlive 后才不wait, 等待着被notify(), 然后t1 die后会调用lock.notifyAll()。
- 注意:这里lock.wait(0)虽然在t1.join()内,但是join()内的代码不是运行在t1线程中,而是运行在main()线程中,
-
*/
2. 两个线程轮流打印数字,一直到100
| package com.example.javatest.theardTest.MultiThreadAlgorithm; |
| |
| |
| |
| |
| |
| |
| |
| |
| public class TakeTurnsPrint { |
| |
| public static class TakeTurns { |
| |
| private static boolean flag = true; |
| |
| private static int count = 0; |
| |
| public synchronized void print1() { |
| for (int i = 1; i <= 50; i++) { |
| while (!flag) { |
| try { |
| System.out.println("print1: wait before"); |
| wait(); |
| System.out.println("print1: wait after"); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| System.out.println("print1: " + ++count); |
| flag = !flag; |
| notifyAll(); |
| } |
| } |
| |
| public synchronized void print2() { |
| for (int i = 1; i <= 50; i++) { |
| while (flag) { |
| try { |
| System.out.println("print2: wait before"); |
| wait(); |
| System.out.println("print2: wait after"); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| System.out.println("print2: " + ++count); |
| flag = !flag; |
| notifyAll(); |
| } |
| } |
| } |
| |
| public static void main(String[] args){ |
| |
| TakeTurns takeTurns = new TakeTurns(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| takeTurns.print1(); |
| } |
| }).start(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| takeTurns.print2(); |
| } |
| }).start(); |
| |
| } |
| |
| } |
| |
| |
3. 写两个线程,一个线程打印1~ 52,另一个线程打印A~Z,打印顺序是12A34B…5152Z
| package com.example.javatest.theardTest.MultiThreadAlgorithm; |
| |
| |
| |
| |
| public class TakeTurnsPrint2 { |
| private boolean flag; |
| private int count; |
| |
| public synchronized void printNum() { |
| for (int i = 0; i < 26; i++) { |
| while (flag) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = !flag; |
| System.out.print(++count); |
| System.out.print(++count); |
| notify(); |
| } |
| } |
| |
| public synchronized void printLetter() { |
| for (int i = 0; i < 26; i++) { |
| while (!flag) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = !flag; |
| System.out.print((char) (65 + i)); |
| notify(); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| TakeTurnsPrint2 turnsPrint2 = new TakeTurnsPrint2(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| turnsPrint2.printNum(); |
| } |
| }).start(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| turnsPrint2.printLetter(); |
| } |
| }).start(); |
| } |
| } |
| |
4. 编写一个程序,启动三个线程,三个线程的ID分别是A,B,C;,每个线程将自己的ID值在屏幕上打印5遍,打印顺序是ABCABC…
| package com.example.javatest.theardTest.MultiThreadAlgorithm; |
| |
| |
| |
| |
| public class ABCABCABC { |
| |
| private int flag = 0; |
| |
| public synchronized void printA() { |
| for(int i = 0; i < 5; i++) { |
| while (flag != 0) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = 1; |
| System.out.print("A"); |
| notifyAll(); |
| } |
| } |
| |
| public synchronized void printB() { |
| for(int i = 0; i < 5; i++) { |
| while (flag != 1) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = 2; |
| System.out.print("B"); |
| notifyAll(); |
| } |
| } |
| |
| public synchronized void printC() { |
| for(int i = 0; i < 5; i++) { |
| while (flag != 2) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = 0; |
| System.out.print("C"); |
| notifyAll(); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| ABCABCABC abcabcabc = new ABCABCABC(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| abcabcabc.printA(); |
| } |
| }).start(); |
| |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| abcabcabc.printB(); |
| } |
| }).start(); |
| |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| abcabcabc.printC(); |
| } |
| }).start(); |
| } |
| } |
| |
| |
5. 编写10个线程,第一个线程从1加到10,第二个线程从11加20…第十个线程从91加到100,最后再把10个线程结果相加。
| |
| |
| |
| public class TenThreadSum { |
| |
| public static class SumThread extends Thread{ |
| |
| int forct = 0; int sum = 0; |
| |
| SumThread(int forct){ |
| this.forct = forct; |
| } |
| |
| @Override |
| public void run() { |
| for(int i = 1; i <= 10; i++){ |
| sum += i + forct * 10; |
| } |
| System.out.println(getName() + " " + sum); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| int result = 0; |
| |
| for(int i = 0; i < 10; i++){ |
| SumThread sumThread = new SumThread(i); |
| sumThread.start(); |
| try { |
| sumThread.join(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| result = result + sumThread.sum; |
| } |
| System.out.println("result " + result); |
| } |
| } |
| |
6. 三个窗口同时卖票
| |
| |
| |
| |
| |
| |
| |
| class Ticket { |
| private int count = 1; |
| public void sale() { |
| while (true) { |
| synchronized (this) { |
| if (count > 200) { |
| System.out.println("票已经卖完啦"); |
| break; |
| } else { |
| System.out.println(Thread.currentThread().getName() + "卖的第 " + count++ + " 张票"); |
| } |
| try { |
| Thread.sleep(200); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| class SaleWindows extends Thread { |
| |
| private Ticket ticket; |
| |
| public SaleWindows(String name, Ticket ticket) { |
| super(name); |
| this.ticket = ticket; |
| } |
| |
| @Override |
| public void run() { |
| super.run(); |
| ticket.sale(); |
| } |
| } |
| |
| public class TicketDemo { |
| public static void main(String[] args) { |
| Ticket ticket = new Ticket(); |
| |
| SaleWindows windows1 = new SaleWindows("窗口1", ticket); |
| SaleWindows windows2 = new SaleWindows("窗口2", ticket); |
| SaleWindows windows3 = new SaleWindows("窗口3", ticket); |
| |
| windows1.start(); |
| windows2.start(); |
| windows3.start(); |
| } |
| } |
| |
| |
| |
7. 生产者消费者
7.1 synchronized方式
| |
| public class FruitPlateDemo { |
| |
| private final static String LOCK = "lock"; |
| |
| private int count = 0; |
| |
| private static final int FULL = 10; |
| |
| public static void main(String[] args) { |
| |
| FruitPlateDemo fruitDemo1 = new FruitPlateDemo(); |
| |
| for (int i = 1; i <= 5; i++) { |
| new Thread(fruitDemo1.new Producer(), "生产者-" + i).start(); |
| new Thread(fruitDemo1.new Consumer(), "消费者-" + i).start(); |
| } |
| } |
| |
| class Producer implements Runnable { |
| @Override |
| public void run() { |
| for (int i = 0; i < 10; i++) { |
| synchronized (LOCK) { |
| while (count == FULL) { |
| try { |
| LOCK.wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| System.out.println("生产者 " + Thread.currentThread().getName() + " 总共有 " + ++count + " 个资源"); |
| LOCK.notifyAll(); |
| } |
| } |
| } |
| } |
| |
| class Consumer implements Runnable { |
| @Override |
| public void run() { |
| for (int i = 0; i < 10; i++) { |
| synchronized (LOCK) { |
| while (count == 0) { |
| try { |
| LOCK.wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| System.out.println("消费者 " + Thread.currentThread().getName() + " 总共有 " + --count + " 个资源"); |
| LOCK.notifyAll(); |
| } |
| } |
| } |
| } |
| } |
7.2 ReentrantLock方式 (可以保证顺序)
| public class Demo1 { |
| |
| private int count = 0; |
| |
| private final static int FULL = 10; |
| |
| private Lock lock; |
| |
| private Condition notEmptyCondition; |
| |
| private Condition notFullCondition; |
| |
| { |
| lock = new ReentrantLock(); |
| notEmptyCondition = lock.newCondition(); |
| notFullCondition = lock.newCondition(); |
| |
| } |
| |
| class Producer implements Runnable { |
| |
| @Override |
| public void run() { |
| |
| for (int i = 0; i < 10; i++) { |
| lock.lock(); |
| try { |
| while(count == FULL) { |
| try { |
| notFullCondition.await(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| System.out.println("生产者 " + Thread.currentThread().getName() + " 总共有 " + ++count + " 个资源"); |
| notEmptyCondition.signal(); |
| } finally { |
| lock.unlock(); |
| } |
| } |
| } |
| } |
| |
| class Consumer implements Runnable { |
| @Override |
| public void run() { |
| for (int i = 0; i < 10; i++) { |
| lock.lock(); |
| try { |
| while(count == 0) { |
| try { |
| notEmptyCondition.await(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| System.out.println("消费者 " + Thread.currentThread().getName() + " 总共有 " + --count + " 个资源"); |
| notFullCondition.signal(); |
| } finally { |
| lock.unlock(); |
| } |
| } |
| } |
| } |
| |
| public static void main(String[] args) { |
| Demo1 demo1 = new Demo1(); |
| for (int i = 1; i <= 5; i++) { |
| new Thread(demo1.new Producer(), "生产者-" + i).start(); |
| new Thread(demo1.new Consumer(), "消费者-" + i).start(); |
| } |
| } |
| } |
| |
7.3 BlockingQueue方式
| import java.util.concurrent.ArrayBlockingQueue; |
| import java.util.concurrent.BlockingQueue; |
| |
| public class Demo2 { |
| |
| private int count = 0; |
| |
| private BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10); |
| |
| public static void main(String[] args) { |
| |
| Demo2 demo2 = new Demo2(); |
| for (int i = 1; i <= 5; i++) { |
| new Thread(demo2.new Producer(), "生产者-" + i).start(); |
| new Thread(demo2.new Consumer(), "消费者-" + i).start(); |
| } |
| } |
| |
| class Producer implements Runnable { |
| |
| @Override |
| public void run() { |
| |
| for (int i = 0; i < 10; i++) { |
| try { |
| queue.put(1); |
| System.out.println("生产者 " + Thread.currentThread().getName() + " 总共有 " + ++count + " 个资源"); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| class Consumer implements Runnable { |
| |
| @Override |
| public void run() { |
| for (int i = 0; i < 10; i++) { |
| try { |
| queue.take(); |
| System.out.println("消费者 " + Thread.currentThread().getName() + " 总共有 " + --count + " 个资源"); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| |
8. 交替打印两个数组
| package com.example.javatest.theardTest.MultiThreadAlgorithm; |
| |
| public class TwoArr { |
| |
| int[] arr1 = new int[]{1, 3, 5, 7, 9}; |
| int[] arr2 = new int[]{2, 4, 6, 8, 10}; |
| |
| boolean flag; |
| |
| public synchronized void print1(){ |
| for(int i= 0; i < arr1.length; i++){ |
| while (flag){ |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = !flag; |
| System.out.println(arr1[i]); |
| notifyAll(); |
| } |
| } |
| |
| public synchronized void print2(){ |
| for(int i= 0; i < arr2.length; i++){ |
| while (!flag){ |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| flag = !flag; |
| System.out.println(arr2[i]); |
| notifyAll(); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| TwoArr twoArr = new TwoArr(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| twoArr.print1(); |
| } |
| }).start(); |
| |
| new Thread(new Runnable() { |
| @Override |
| public void run() { |
| twoArr.print2(); |
| } |
| }).start(); |
| } |
| |
| } |
| |
| |
9. 使用多线程,模拟龟兔赛跑的场景。
| |
| |
| public class ThreadTest1 extends Thread{ |
| |
| @Override |
| public void run() { |
| try { |
| pao(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| private static void pao() throws InterruptedException { |
| for(int i=1;i<=10;i++) { |
| System.out.println(Thread.currentThread().getName()+"打卡:"+i+"米"); |
| Thread.sleep(1000); |
| } |
| } |
| |
| } |
| |
| public class ThreadTest2 { |
| |
| public static void main(String[] args) { |
| Thread th1=new ThreadTest1(); |
| Thread th2=new ThreadTest1(); |
| |
| th1.setName("龟"); |
| th2.setName("兔"); |
| |
| th1.start(); |
| th2.start(); |
| } |
| } |
10. 编写一个有两个线程的程序,第一个线程用来计算2~100000之间的素数的个数,第二个线程用来计算100000~200000之间的素数的个数,最后输出结果。
| |
| public class ThreadTest3 implements Runnable { |
| |
| @Override |
| public void run() { |
| int a=fun1(); |
| System.out.println("一素数个数:"+a); |
| } |
| |
| private static int fun1() { |
| |
| int sum = 0; |
| |
| for (int i = 2; i <= 100000; i++) { |
| int j=2; |
| while(i%j!=0) { |
| j++; |
| } |
| if(j==i) { |
| sum++; |
| } |
| |
| } |
| |
| return sum; |
| } |
| |
| } |
| public class ThreadTest5 implements Runnable{ |
| |
| @Override |
| public void run() { |
| int a=fun2(); |
| System.out.println("二素数个数:"+a); |
| } |
| |
| private static int fun2() { |
| |
| int sum = 0; |
| |
| for (int i = 100000; i <= 200000; i++) { |
| int j=2; |
| while(i%j!=0) { |
| j++; |
| } |
| if(j==i) { |
| sum++; |
| } |
| |
| } |
| |
| return sum; |
| } |
| |
| } |
| public class ThreadTest4 { |
| public static void main(String[] args) { |
| ThreadTest3 th=new ThreadTest3(); |
| Thread th1=new Thread(th); |
| th1.start(); |
| |
| ThreadTest5 th2=new ThreadTest5(); |
| Thread th3=new Thread(th2); |
| th3.start(); |
| } |
| |
| } |
11. 使用多线程实现多个文件同步复制功能,并在控制台显示复制的进度,进度以百分比表示。例如:把文件A复制到E盘某文件夹下,在控制台上显示“XXX文件已复制10%”,“XXX文件已复制20%”……“XXX文件已复制100%”,“XXX复制完成!”
//重点:java.text.DecimalFormat的使用(格式化十进制数)
| package two; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.text.DecimalFormat; |
| |
| public class CopyFile extends Thread{ |
| |
| public File older; |
| public File newer; |
| |
| |
| public CopyFile(String older, String newer) { |
| this.older = new File(older); |
| this.newer = new File(newer); |
| } |
| |
| @Override |
| public void run() { |
| FileInputStream fis=null; |
| FileOutputStream fos=null; |
| |
| try { |
| fis=new FileInputStream(older); |
| fos=new FileOutputStream(newer); |
| |
| long len=older.length(); |
| |
| |
| |
| byte[] b=new byte[(int) (older.length()/10)]; |
| int length=0; |
| |
| |
| System.out.println(len); |
| double temp=0; |
| |
| DecimalFormat df=new DecimalFormat("##%"); |
| |
| |
| while((length = fis.read(b)) !=-1) { |
| fos.write(b, 0, length); |
| temp +=length; |
| double d=temp/len; |
| |
| int jd=(int) d; |
| if(jd%10==0) { |
| System.out.println(older.getName()+"文件复制了:"+df.format(d)); |
| } |
| System.out.println(older.getName()+"文件已复制了:"+d); |
| } |
| System.out.println(older.getName()+"复制完毕!"); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| }finally { |
| try { |
| fis.close(); |
| fos.close(); |
| } catch (Exception e2) { |
| e2.printStackTrace(); |
| } |
| } |
| } |
| } |
| |
| package two; |
| |
| public class CopyTest { |
| |
| public static void main(String[] args) { |
| |
| CopyFile cf1=new CopyFile("G://金泰妍.MP3", "F://金泰妍.MP3"); |
| CopyFile cf2=new CopyFile("G://GD.MP3", "F://GD.MP3"); |
| cf1.start(); |
| cf2.start(); |
| } |
| } |
| |
12. 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。考虑到线程的安全性写出程序。
| package test.one; |
| |
| |
| |
| public class Test1 { |
| |
| private int j; |
| |
| public static void main(String[] args) { |
| Test1 t=new Test1(); |
| Add add=t.new Add(); |
| Sub sub=t.new Sub(); |
| |
| for(int i=0;i<2;i++){ |
| Thread t1=new Thread(add); |
| t1.start(); |
| Thread t2=new Thread(sub); |
| t2.start(); |
| } |
| |
| |
| } |
| |
| |
| private synchronized void add(){ |
| j++; |
| System.out.println(Thread.currentThread().getName()+":"+j); |
| } |
| |
| private synchronized void sub(){ |
| j--; |
| System.out.println(Thread.currentThread().getName()+":"+j); |
| } |
| |
| class Add implements Runnable{ |
| |
| |
| @Override |
| public void run() { |
| for (int i=0;i<10;i++){ |
| add(); |
| } |
| } |
| } |
| |
| class Sub implements Runnable{ |
| |
| |
| @Override |
| public void run() { |
| for (int i=0;i<10;i++){ |
| sub(); |
| } |
| } |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~