多线程练习题
1.使用多线程,模拟龟兔赛跑的场景。
线程类:
1 //模拟龟兔百米赛跑 2 3 public class ThreadTest1 extends Thread{ 4 5 @Override 6 public void run() { 7 try { 8 pao(); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 } 13 14 private static void pao() throws InterruptedException { 15 for(int i=1;i<=10;i++) { 16 System.out.println(Thread.currentThread().getName()+"打卡:"+i+"米"); 17 Thread.sleep(1000); 18 } 19 } 20 21 }
测试类:
1 public class ThreadTest2 { 2 3 public static void main(String[] args) { 4 Thread th1=new ThreadTest1(); 5 Thread th2=new ThreadTest1(); 6 7 th1.setName("龟"); 8 th2.setName("兔"); 9 10 th1.start(); 11 th2.start(); 12 } 13 }
测试结果:
兔打卡:1米
龟打卡:1米
龟打卡:2米
兔打卡:2米
龟打卡:3米
兔打卡:3米
兔打卡:4米
龟打卡:4米
龟打卡:5米
兔打卡:5米
兔打卡:6米
龟打卡:6米
龟打卡:7米
兔打卡:7米
龟打卡:8米
兔打卡:8米
兔打卡:9米
龟打卡:9米
兔打卡:10米
龟打卡:10米
2、编写一个有两个线程的程序,第一个线程用来计算2~100000之间的素数的个数,第二个线程用来计算100000~200000之间的素数的个数,最后输出结果。
第一个线程类:
1 //线程类,以及判断素数的方法 2 public class ThreadTest3 implements Runnable { 3 4 @Override 5 public void run() { 6 int a=fun1(); 7 System.out.println("一素数个数:"+a); 8 } 9 10 private static int fun1() { 11 12 int sum = 0;// 素数个数 13 14 for (int i = 2; i <= 100000; i++) {// 某个数 15 int j=2; 16 while(i%j!=0) { 17 j++; 18 } 19 if(j==i) { 20 sum++; 21 } 22 23 } 24 25 return sum; 26 } 27 28 }
第二个线程类:
1 public class ThreadTest5 implements Runnable{ 2 3 @Override 4 public void run() { 5 int a=fun2(); 6 System.out.println("二素数个数:"+a); 7 } 8 9 private static int fun2() { 10 11 int sum = 0;// 素数个数 12 13 for (int i = 100000; i <= 200000; i++) {// 某个数 14 int j=2; 15 while(i%j!=0) { 16 j++; 17 } 18 if(j==i) { 19 sum++; 20 } 21 22 } 23 24 return sum; 25 } 26 27 }
测试:
1 public class ThreadTest4 { 2 public static void main(String[] args) { 3 ThreadTest3 th=new ThreadTest3(); 4 Thread th1=new Thread(th); 5 th1.start(); 6 7 ThreadTest5 th2=new ThreadTest5(); 8 Thread th3=new Thread(th2); 9 th3.start(); 10 } 11 12 }
结果:
一素数个数:9592 二素数个数:8392
3、使用多线程实现多个文件同步复制功能,并在控制台显示复制的进度,进度以百分比表示。例如:把文件A复制到E盘某文件夹下,在控制台上显示“XXX文件已复制10%”,“XXX文件已复制20%”……“XXX文件已复制100%”,“XXX复制完成!”
//重点:java.text.DecimalFormat的使用(格式化十进制数)
1 package two; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.text.DecimalFormat; 7 8 public class CopyFile extends Thread{ 9 10 public File older;//源文件路径 11 public File newer;//目标文件路径 12 13 //构造函数把路径封装成文件 14 public CopyFile(String older, String newer) { 15 this.older = new File(older); 16 this.newer = new File(newer); 17 } 18 19 @Override 20 public void run() { 21 FileInputStream fis=null; 22 FileOutputStream fos=null; 23 24 try { 25 fis=new FileInputStream(older); 26 fos=new FileOutputStream(newer); 27 28 long len=older.length();//获取源文件的长度 跟 fis.available()的结果 29 30 31 //文件大小的十分之一 32 byte[] b=new byte[(int) (older.length()/10)];//声明一个字节数组,每次读取的数据存到这里 33 int length=0;//返回每次读取的数据长度 34 35 36 System.out.println(len); 37 double temp=0; 38 39 DecimalFormat df=new DecimalFormat("##%"); 40 41 //最多将b.length个字节读入一个byte数组中,也就是每次读1/10个字节,然后循环,直到读到问价尾 42 while((length = fis.read(b)) !=-1) {//读到文件尾会返回-1 43 fos.write(b, 0, length);//把每次读取的内容,输出到目标路径文件中 44 temp +=length;//把每次读取的数据长度累加 45 double d=temp/len;//计算出已经读取的长度占文件总长度的比率 46 47 int jd=(int) d; 48 if(jd%10==0) { 49 System.out.println(older.getName()+"文件复制了:"+df.format(d));//将小数给格式化 50 } 51 System.out.println(older.getName()+"文件已复制了:"+d); 52 } 53 System.out.println(older.getName()+"复制完毕!"); 54 55 } catch (Exception e) { 56 e.printStackTrace(); 57 }finally { 58 try { 59 fis.close(); 60 fos.close(); 61 } catch (Exception e2) { 62 e2.printStackTrace(); 63 } 64 } 65 } 66 }
测试:
1 package two; 2 3 public class CopyTest { 4 5 public static void main(String[] args) { 6 //两个线程实例 7 CopyFile cf1=new CopyFile("G://金泰妍.MP3", "F://金泰妍.MP3"); 8 CopyFile cf2=new CopyFile("G://GD.MP3", "F://GD.MP3"); 9 cf1.start(); 10 cf2.start(); 11 } 12 }
结果:
3378348//输出的是文件的大小 3817572 GD.MP3文件复制了:10% GD.MP3文件已复制了:0.09999976319787067 金泰妍.MP3文件复制了:10% 金泰妍.MP3文件已复制了:0.09999994761068029 GD.MP3文件复制了:20% GD.MP3文件已复制了:0.19999952639574134 金泰妍.MP3文件复制了:20% 金泰妍.MP3文件已复制了:0.19999989522136058 GD.MP3文件复制了:30% GD.MP3文件已复制了:0.29999928959361205 金泰妍.MP3文件复制了:30% 金泰妍.MP3文件已复制了:0.2999998428320409 GD.MP3文件复制了:40% GD.MP3文件已复制了:0.3999990527914827 金泰妍.MP3文件复制了:40% 金泰妍.MP3文件已复制了:0.39999979044272116 GD.MP3文件复制了:50% GD.MP3文件已复制了:0.49999881598935336 金泰妍.MP3文件复制了:50% 金泰妍.MP3文件已复制了:0.4999997380534015 GD.MP3文件复制了:60% GD.MP3文件已复制了:0.5999985791872241 金泰妍.MP3文件复制了:60% 金泰妍.MP3文件已复制了:0.5999996856640818 GD.MP3文件复制了:70% 金泰妍.MP3文件复制了:70% GD.MP3文件已复制了:0.6999983423850947 金泰妍.MP3文件已复制了:0.6999996332747621 GD.MP3文件复制了:80% GD.MP3文件已复制了:0.7999981055829654 金泰妍.MP3文件复制了:80% 金泰妍.MP3文件已复制了:0.7999995808854423 GD.MP3文件复制了:90% GD.MP3文件已复制了:0.8999978687808361 金泰妍.MP3文件复制了:90% 金泰妍.MP3文件已复制了:0.8999995284961226 GD.MP3文件复制了:100% GD.MP3文件已复制了:0.9999976319787067 GD.MP3文件已复制了:1.0 GD.MP3复制完毕! 金泰妍.MP3文件复制了:100% 金泰妍.MP3文件已复制了:0.999999476106803 金泰妍.MP3文件已复制了:1.0 金泰妍.MP3复制完毕!
4、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。考虑到线程的安全性写出程序。
1 package test.one; 2 3 //4、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。考虑到线程的安全性写出程序。 4 //使线程同步 5 public class Test1 {//一个主线程 6 7 private int j;//变量j 8 9 public static void main(String[] args) { 10 Test1 t=new Test1(); 11 Add add=t.new Add();//内部类的实例 12 Sub sub=t.new Sub(); 13 14 for(int i=0;i<2;i++){//循环两边创建四个线程,两加两减 15 Thread t1=new Thread(add); 16 t1.start(); 17 Thread t2=new Thread(sub); 18 t2.start(); 19 } 20 21 22 } 23 24 //考虑线程安全的问题,为方法加synchronized关键字,保证一时间只有一个线程操作该方法 25 private synchronized void add(){ 26 j++; 27 System.out.println(Thread.currentThread().getName()+":"+j); 28 } 29 30 private synchronized void sub(){ 31 j--; 32 System.out.println(Thread.currentThread().getName()+":"+j); 33 } 34 35 class Add implements Runnable{//线程,成员内部类无条件访问外部类的所有成员 36 37 //线程调用了j+的方法 38 @Override 39 public void run() { 40 for (int i=0;i<10;i++){ 41 add(); 42 } 43 } 44 } 45 46 class Sub implements Runnable{//线程,同上 47 48 //线程调用了j-的方法 49 @Override 50 public void run() { 51 for (int i=0;i<10;i++){ 52 sub(); 53 } 54 } 55 } 56 }
测试结果(不唯一):
"C:\Program Files\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.3.4\lib\idea_rt.jar=64983:C:\Program Files\JetBrains\IntelliJ IDEA 2018.3.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;G:\IDEA-JAVA-Test\out\production\one" test.one.Test1 Thread-0:1 Thread-1:0 Thread-1:-1 Thread-1:-2 Thread-1:-3 Thread-1:-4 Thread-1:-5 Thread-1:-6 Thread-1:-7 Thread-1:-8 Thread-1:-9 Thread-0:-8 Thread-0:-7 Thread-0:-6 Thread-0:-5 Thread-0:-4 Thread-0:-3 Thread-0:-2 Thread-0:-1 Thread-0:0 Thread-2:1 Thread-2:2 Thread-2:3 Thread-2:4 Thread-2:5 Thread-2:6 Thread-2:7 Thread-2:8 Thread-2:9 Thread-2:10 Thread-3:9 Thread-3:8 Thread-3:7 Thread-3:6 Thread-3:5 Thread-3:4 Thread-3:3 Thread-3:2 Thread-3:1 Thread-3:0