package com.bilibli.kuangshen.test; //创建线程方式一:继承Thread类,重写run()方法,调用start开启线程 public class TestThread extends Thread{ @Override public void run() { //run方法线程体 for (int i = 0; i < 20; i++) { System.out.println("我在看代码1111"); } } public static void main(String[] args) { //创建线程对象 TestThread testThread1 = new TestThread(); //调用start()方法开启线程 testThread1.start();; for (int i = 0; i < 200; i++) { System.out.println("我在学习多线程"); } } }
总结:线程开启不一定执行,由CPU调度执行
package com.bilibli.kuangshen.test; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //练习Thread,实现多线程同步下载图片 public class TestThread2 extends Thread{ private String url; //网络图片地址 private String name; //保存的文件名 public TestThread2(String url ,String name){ this.url = url; this.name = name; } //下载图片的执行体 @Override public void run(){ WebDownLoader webDownLoader = new WebDownLoader(); webDownLoader.downloader(url,name); System.out.println("下载了文件名为" + name); } public static void main(String[] args) { TestThread2 t1 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","1.png"); TestThread2 t2 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","2.png"); TestThread2 t3 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","3.png"); t1.start(); t2.start(); t3.start(); } } //下载器 class WebDownLoader{ public void downloader(String url , String name){ try { FileUtils.copyURLToFile(new URL(url), new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("IO异常,downloader方法出现问题"); } } }
主要区别:
package com.bilibli.kuangshen.test; //多个线程同时操作一个对象 //买火车票的例子 //发现一个问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱。(并发问题) public class TestThread4 implements Runnable{ private int ticketNums = 10; @Override public void run(){ while(true){ if (ticketNums <= 0){ break; } try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-->拿到了" +ticketNums-- +"票"); } } public static void main(String[] args) { TestThread4 ticket = new TestThread4(); new Thread(ticket,"小明").start(); new Thread(ticket,"老师").start(); new Thread(ticket,"黄牛").start(); } }
package com.bilibli.kuangshen.test; //模拟龟兔赛跑 public class Race implements Runnable { //胜利者 private static String winner; @Override public void run(){ for (int i = 0; i <= 1000; i++) { //模拟兔子休息 if (Thread.currentThread().getName().equals("兔子") && i%50 == 0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameOver(i); //如果比赛结束了,就停止程序 if(flag){ break; } System.out.println(Thread.currentThread().getName()+"-->跑了"+ i + "步" ); } } //判断是否完成比赛。 private boolean gameOver( int steps){ //判断是否有胜利者 if (winner != null) { //已有胜利者。 return true; }{ if(steps >= 1000){ winner = Thread.currentThread().getName(); System.out.println("Winner is " + winner); return true; } } return false ; } public static void main(String[] args) { Race race = new Race(); new Thread(race,"乌龟").start(); new Thread(race,"兔子").start(); } }
与Runnable不同的是,Callable需要返回值