1.程序线程、进程、
process 和thread
进程是程序一次执行的过程
一个进程可以包含若干个线程
一个进程至少一个线程
很多多线程都是模拟出来的,真的多线程是有多个cpu同时。
在程序运行时,即使自己没有创建线程,后台也会有多个线程,如main线程,gc线程等等
如果开辟了多个线程,线程由调度器安排不能人为干预。
对同一个资源操作的时候,会存在资源抢夺的问题,需要加入并发控制,
线程会带来额外的开销,cpu调度时间,并发控制时间。
每个线程在自己的工作内存交汇,可能造成数据不一致。
2.线程创建
三种创建方式:
-
继承Thread类
-
实现Runable接口
-
实现Callable接口
第一种方法具体过程:
自定义类继承Thread类
重写run方法,编写执行体
创建线程对象,调用start方法启动线程。
(线程不一定立即执行。)
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; public class CreateThread2 extends Thread{ private String url; private String name; public CreateThread2(String name, String url) { super(name); this.url = url; this.name = name; } public CreateThread2() { } @Override public void run() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为"+name); } public static void main(String[] args) { CreateThread2 createThread2 = new CreateThread2("会更好.jpg","https://tse4-mm.cn.bing.net/th/id/OIP-C.Xf1A2zKMTZ8-O6eXMk72hAHaFE?w=223&h=180&c=7&r=0&o=5&dpr=1.25&pid=1.7"); createThread2.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方法出现问题"); } } }
第二种方式:
-
创建一个类实现Runable接口
-
重写run方法
-
执行线程需要丢入runnable接口实现类,调用start方法
public class CreateThread3 implements Runnable{ @Override public void run() { // 实现代码 } public static void main(String[] args) { CreateThread3 createThread3 = new CreateThread3(); Thread thread =new Thread(createThread3); thread.start(); } }
第二种方法推荐,因为避免了单继承的局限性,方便一个对象被多个线程使用。
实例:多个线程同时操作同一个对象
public class CreateThread3 implements Runnable{//抢票 int ticketNums= 10; @Override public void run() { // 实现代码 while (true){ if (ticketNums<=0) { break; } System.out.println(Thread.currentThread().getName() + ticketNums-- + "tickets"); } } public static void main(String[] args) { CreateThread3 createThread3 = new CreateThread3(); Thread thread = new Thread(createThread3); new Thread(thread,"小明").start(); new Thread(thread,"老师").start(); new Thread(thread,"黄牛党").start(); }
例子:双人赛跑
public class CreateThread4 implements Runnable{ private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { if (Thread.currentThread().getName().equals("兔子")&& i%10==0){ try {//模拟兔子睡觉 Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } boolean flag =gameOver(i); if (flag) {//两个线程共用flag指示器 break; } System.out.println(Thread.currentThread().getName() + "run" + i + "steps"); } } private boolean gameOver(int steps){ if (winner!=null){//判断比赛结束 return true; } if (steps==100){ winner= Thread.currentThread().getName(); System.out.println("winner is"+winner); return true; } return false; } public static void main(String[] args) { CreateThread4 createThread4= new CreateThread4(); new Thread(createThread4,"兔子").start(); new Thread(createThread4,"乌龟").start(); }
第三种实现方式:实现Callable接口
-
实现Callable接口
-
重写call方法
-
创建目标对象
-
创建执行服务:ExecutorService ser= Executors .newFixedThreadPool(1);
-
提交执行:Future<Boolean>result1=ser.submit(t1);
-
获取结果:boolean r1 =result1.get();
-
关闭服务:ser.shutdownNow();
import java.util.concurrent.*; public class CreateThread5 implements Callable { private String url; private String name; public CreateThread5(String name, String url) { this.url = url; this.name = name; } public CreateThread5() { } @Override public Object call() throws Exception { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为"+name); return null; } public static void main(String[] args) throws ExecutionException, InterruptedException { CreateThread5 createThread51 = new CreateThread5("会更好.jpg","https://tse4-mm.cn.bing.net/th/id/OIP-C.Xf1A2zKMTZ8-O6eXMk72hAHaFE?w=223&h=180&c=7&r=0&o=5&dpr=1.25&pid=1.7"); ExecutorService executorService = Executors.newFixedThreadPool(1); Future<Boolean> rst =executorService.submit(createThread51); boolean rs1 = rst.get(); executorService.shutdown(); }