1.继承Thread类
- 创建一个类集成Thread类
- 重写run() 方法
- 调用start() 开启多线程
public class Demo01 extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("这是多线程调用----------"); } //super.run(); } //run()方法是先执行多线程方法,再执行主线程方法。 //start()方法是开启多线程,主线程和多线程方法交替执行。线程并不是立即执行,由CPU进行调度安排,不可控 public static void main(String[] args) { Demo01 demo01 = new Demo01(); demo01.start(); for (int i = 0; i < 2000; i++) { System.out.println(i+"这是主线程调用-------"); } } }
PS:根据个人电脑得配置不同,执行的结果也有可能不同,如果看不出效果,不妨把主线程得执行次数调大。
2.实现Runnable接口
- 写一个类,实现Runnable接口
- 重写run() 方法
- 在执行多线程时需要丢入Runnable接口得实现类
public class Demo03 implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("这是线程执行方法-----------"); } } public static void main(String[] args) { Demo03 demo03 = new Demo03(); Thread thread = new Thread(demo03); thread.start(); for (int i = 0; i < 200; i++) { System.out.println(i+"这是主线程执行的方法----------"); } } }
小练习:
1.三个人抢500张票
public class SynTest implements Runnable{
private Integer totalTicket = 500;
private Boolean flag = true;
private synchronized void buy(){
if (totalTicket <= 0){
flag = false;
return;
}
try {
Thread.sleep(10);
}catch (Exception e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了第"+totalTicket--+"张票");
}
public static void main(String[] args) {
SynTest synTest = new SynTest();
new Thread(synTest,"小明").start();
new Thread(synTest,"老师").start();
new Thread(synTest,"黄牛").start();
}
@Override
public void run() {
while (flag){
buy();
}
}
}
2.模拟龟兔赛跑
public class Race implements Runnable{
private static String winner;
//private Boolean flag;
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean flag = gameOver(i);
if (flag){
//System.out.println("胜利者是"+Thread.currentThread().getName());
break;
}
System.out.println(Thread.currentThread().getName()+"---跑了"+i+"步");
}
}
public boolean gameOver(int temp){
if (winner != null){
return true;
}{
if (temp>=100){
winner = Thread.currentThread().getName();
System.out.println("胜利者是"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
3.实现Callable接口
总体看实现callable与实现runnable接口方式是一样的,区别在于实现callable比实现runnable接口功能更强大,具体表现:
callable可以在任务结束后返回一个值,而runnable不行;
callable可以向外抛出异常,而runnable的run()方法不行;
可以通过运行Callable得到Fulture对象监听目标线程调用call方法的结果,得到返回值。(fulture.get(),调用后会阻塞,直到获取到返回值)
实现步骤:
- 创建一个callable接口的子类实例化对象;
- 重写call方法,将要在线程中执行的方法写在其中;
- 创建ExecutorService线程池;
- 将自定义的对象或开启的线程数量放入到线程池里面;
- 提交执行;
- 获取返回结果;
- 关闭线程池,不再接收新的线程,未结束的线程不会停止;
import org.apache.commons.io.FileUtils; import java.io.File; import java.net.URL; import java.util.concurrent.*; /** * 实现callable的方式开启多线程 */ public class Demo01 implements Callable<Boolean> { private String url; private String name; public Demo01(String url, String name) { this.url = url; this.name = name; } @Override public Boolean call() throws Exception { DownLoadService downLoadService = new DownLoadService(); downLoadService.down(url,name); System.out.println("已经下载了文件名为:"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { Demo01 t1 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "01.jpg"); Demo01 t2 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "02.jpg"); Demo01 t3 = new Demo01("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201708%2F17%2F20170817165222_uG8XZ.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619853513&t=b0beb9a2d2d044e227e0ed99002fc1c5", "03.jpg"); //创建执行服务 ExecutorService es = Executors.newFixedThreadPool(3); //提交执行 Future<Boolean> s1 = es.submit(t1); Future<Boolean> s2 = es.submit(t2); Future<Boolean> s3 = es.submit(t3); //获取执行结果 Boolean b1 = s1.get(); Boolean b2 = s2.get(); Boolean b3 = s3.get(); es.shutdown(); } } class DownLoadService{ public void down(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); }catch (Exception e){ e.printStackTrace(); System.out.println("down方法抛出异常。"); } } }