一个程序就是一个进程(一个pid),一个进程可以开多个线程
说起进程,就不得不说下程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
而进程(Process)则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位
通常在一个进程中可以包含若干个线程(Thread),当然一个进程中至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的的单位。
注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个epu的情况下,在同一个时何点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。
创建线程有三种方法,分别是:继承Thread类,实现Runnable接口、实现Callable接口
包:java.Thread
package com.LearnThread; // 继承Thread类,重写run方法,调用start // 线程开启不一定立即执行,由cpu调度执行 public class FirstThread extends Thread { @Override public void run() { // run方法线程体 System.out.println("我是run线程"); } public static void main(String[] args) { // 主线程 线程体 FirstThread f = new FirstThread(); // new一个线程对象 f.start(); // 启动线程 System.out.println("我是主线程"); // 主线程 } }
添加commons-io包:
代码:
package com.LearnThread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; // 使用多线程下载图片 public class DownloadImg extends Thread { private String url; private String name; public DownloadImg(String url, String name) { this.url = url; this.name = name; } @Override public void run() { Download download = new Download(); download.download(url, name); System.out.println("下载了文件名为:" + name); } // 主线程,起了3个子线程去下载图片,这三个线程同时执行,没有顺序 public static void main(String[] args) { DownloadImg t1 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/78ded708c81fa005774e7008dae6429e.png", "1.png"); DownloadImg t2 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/d0b66392a5b4bb2a38d4d7e61565df75.png", "2.png"); DownloadImg t3 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/c4404f374410e86aa75365898390bff2.png", "3.png"); t1.start(); t2.start(); t3.start(); } } class Download { public void download(String url, String name) { // 下载图片的实现方法 try { FileUtils.copyURLToFile(new URL(url), new File(name)); // commons库提供的方法,接收两个参数:网络图片地址、本地存储路径 } catch (IOException e) { e.printStackTrace(); System.out.println("download方法出现异常"); } } }
因为java单继承的局限性,所有推荐使用此该方法来实现多线程
package com.LearnThread; // 实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start public class SecondThread implements Runnable { @Override public void run() { // run方法线程体 System.out.println("我是run线程"); } public static void main(String[] args) { // 主线程 线程体 SecondThread s = new SecondThread(); // new一个Runnable实现类的对象 // Thread t = new Thread(s); // 将Runnable实现类的对象 丢入Thread类 (代理) // t.start(); // 启动线程 new Thread(s).start(); System.out.println("我是主线程"); // 主线程 } }
package com.LearnThread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; // 使用多线程下载图片 public class DownloadImg implements Runnable { private String url; private String name; public DownloadImg(String url, String name) { this.url = url; this.name = name; } @Override public void run() { Download download = new Download(); download.download(url, name); System.out.println("下载了文件名为:" + name); } public static void main(String[] args) { DownloadImg t1 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/78ded708c81fa005774e7008dae6429e.png", "1.png"); DownloadImg t2 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/d0b66392a5b4bb2a38d4d7e61565df75.png", "2.png"); DownloadImg t3 = new DownloadImg("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/c4404f374410e86aa75365898390bff2.png", "3.png"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); } } class Download { public void download(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); // commons库提供的方法,接收两个参数:网络图片地址、本地存储路径 } catch (IOException e) { e.printStackTrace(); System.out.println("download方法出现异常"); } } }
package com.LearnThread; public class ThirdThread implements Runnable { private int number = 10; @Override public void run() { while (true) { if(number<=0){ break; } try { Thread.sleep(1000); // 线程等待方法,单位 毫秒 } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().getName() 获取当前线程名 System.out.println(Thread.currentThread().getName() + " 拿到了第 " + number-- + " 张票"); } } public static void main(String[] args) { ThirdThread t = new ThirdThread(); new Thread(t, "黄牛党").start(); new Thread(t, "老师").start(); new Thread(t, "同学").start(); } }
package com.LearnThread; public class FourthlyThread 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) { break; } System.out.println(Thread.currentThread().getName() + "跑了" + i + "步"); } } // 判断是否完成比赛 public 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) { FourthlyThread race = new FourthlyThread(); new Thread(race, "兔子").start(); new Thread(race, "乌龟").start(); } }
package com.LearnThread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; public class FifthsThread implements Callable { private String url; private String name; public FifthsThread(String url, String name) { this.url = url; this.name = name; } @Override public Object call() throws Exception { Download download = new Download(); download.download(url, name); System.out.println("下载了文件名为:" + name); return true; } public static void main(String[] args) { FifthsThread t1 = new FifthsThread("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/78ded708c81fa005774e7008dae6429e.png", "1.png"); FifthsThread t2 = new FifthsThread("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/d0b66392a5b4bb2a38d4d7e61565df75.png", "2.png"); FifthsThread t3 = new FifthsThread("https://save-img-1306067674.cos.ap-shanghai.myqcloud.com/c4404f374410e86aa75365898390bff2.png", "3.png"); // 创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(3); // 提交执行 Future<Boolean> r1 = ser.submit(t1); Future<Boolean> r2 = ser.submit(t2); Future<Boolean> r3 = ser.submit(t3); // 获取结果 try { boolean res1 = r1.get(); boolean res2 = r2.get(); boolean res3 = r3.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } // 关闭服务 ser.shutdownNow(); } } class Download { public void download(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); // commons库提供的方法,接收两个参数:网络图片地址、本地存储路径 } catch (IOException e) { e.printStackTrace(); System.out.println("download方法出现异常"); } } }
package com.agent; public class AgentThread { public static void main(String[] args) { You you = new You(); // 把真实对象实例化传给代理对象 new Thread( ()-> System.out.println("I love you.") ).start(); // lambda new WeddingCompany(you).happyMarry(); } } // 定义一个结婚接口 interface Marry{ void happyMarry(); } // 真实角色,结婚人 class You implements Marry{ @Override public void happyMarry() { System.out.println("要结婚了,超开心"); } } // 代理角色,帮助结婚 class WeddingCompany implements Marry{ private Marry target; // 代理 真实目标角色 public WeddingCompany(Marry target) { this.target = target; } @Override public void happyMarry() { before(); this.target.happyMarry(); // 这就是真实对象 after(); } private void after() { System.out.println("结婚之后,收尾款"); } private void before() { System.out.println("结婚之前,布置现场"); } }
package com.lambda; public class Lambda { // 实现方式(二、静态内部类) static class Like2 implements ILike{ @Override public void lambda() { System.out.println("I like lambda2"); } } public static void main(String[] args) { // 实现方式(三、局部内部类) class Like3 implements ILike{ @Override public void lambda() { System.out.println("I like lambda3"); } } // 实现方式(四、匿名内部类)没有类名,必须借助接口或者父类 ILike like4 = new ILike(){ @Override public void lambda() { System.out.println("I like lambda4"); } }; ILike like = new Like(); like.lambda(); ILike like2 = new Like2(); like2.lambda(); ILike like3 = new Like3(); like3.lambda(); like4.lambda(); } } // 定义一个函数式接口 interface ILike{ void lambda(); } // 实现方式(一、外部类) class Like implements ILike{ @Override public void lambda() { System.out.println("I like lambda"); } }
不带参数
package com.lambda; public class Lambda { public static void main(String[] args) { // 实现方式(五、lambda表达式) 不带参数 ILike like4 = ()-> System.out.println("I like lambda5"); like4.lambda(); } } // 定义一个函数式接口 interface ILike{ void lambda(); // 函数式接口,可以通过lambda表达式来创建该接口对象 }
带参数
package com.lambda; public class Lambda { public static void main(String[] args) { // 实现方式(五、lambda表达式) 带参数 ILike like = (a, b) -> { System.out.println("I like lambda5 " + a); System.out.println("I like lambda5 " + b); }; like.lambda(2, 3); } } // 定义一个函数式接口 interface ILike { void lambda(int a, int b); }
五大状态:创建状态(NEW)、就绪状态(RUNNABLE)、运行状态(RUNNING)、阻塞状态(TIMED_WAITING)、死亡状态(TERMINATED)
firstThread.setPriority(3); // 更改线程优先级
static void sleep(3); // 让线程休眠3毫秒
void join(); // 等待该线程终止
static void yield(); // 暂停正在执行的线程对象,并执行其他线程
void interrupt(); // 中断线程,不推荐该方式
boolean isAlive(); // 测试线程是否处于活动状态
package com.status; // 1 建议线程正常停止:利用循环次数,但不建议死循环 // 2 建议使用标志位:设置一个标志 public class TestStop implements Runnable { // 设置一个标志位 private boolean flag = true; @Override public void run() { int i = 0; while (flag) { System.out.println("run thread" + i++); } } // 设置一个公开方法改变标识位,停止线程 public void stopFlag(){ this.flag = false; } public static void main(String[] args) { TestStop testStop = new TestStop(); new Thread(testStop).start(); // 启动线程 // 主线程等待100毫秒 Thread.sleep(100); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 改变flag标志位,即终止线程 testStop.stopFlag(); System.out.println("线程该停止了"); } }
package com.status; import java.text.SimpleDateFormat; import java.util.Date; public class TestSleep { public static void main(String[] args) throws InterruptedException { tenDown(); sysTime(); } public static void tenDown() throws InterruptedException { // 倒计时10秒 int num = 10; while (true) { Thread.sleep(1000); System.out.println(num--); if (num < 0) { break; } } } public static void sysTime() throws InterruptedException { // 获取系统时间 10秒 int num = 10; Date nowTime = new Date(System.currentTimeMillis()); // 获取系统时间 while (true) { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(nowTime)); nowTime = new Date(System.currentTimeMillis()); // 更新时间 num--; if (num<0){ break; } } } }
package com.status; public class TestYield { public static void main(String[] args) { MyYield myYield = new MyYield(); new Thread(myYield, "a").start(); new Thread(myYield, "b").start(); } } class MyYield implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "线程开始执行"); Thread.yield(); // 礼让 System.out.println(Thread.currentThread().getName() + "线程停止执行"); } }
package com.status; public class TestJoin implements Runnable { @Override public void run() { for (int i = 0; i <= 100; i++) { try { Thread.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程vip来了" + i); } } public static void main(String[] args) throws InterruptedException { // 启动子线程 TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); // 启动主线程 for (int i = 0; i < 500; i++) { System.out.println("main" + i); if (i == 200) { thread.join(); // 主线程执行到i==200时,停下等待子线程执行 } } } }
thread.getState() 获取线程状态
package com.status; public class TestStatus { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("/////////"); }); // 观察线程状态(NEW) Thread.State state = thread.getState(); System.out.println(state); thread.start(); // 观察线程状态(RUNNABLE) state = thread.getState(); System.out.println(state); while (state != Thread.State.TERMINATED){ // 判断线程不终止 Thread.sleep(100); state = thread.getState(); System.out.println(state); } } }
package com.status; public class TestPriority { public static void main(String[] args) { // 主线程优先级,默认为5,无法修改 System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority()); MyPriority myPriority = new MyPriority(); Thread t1 = new Thread(myPriority, "t1"); Thread t2 = new Thread(myPriority, "t2"); Thread t3 = new Thread(myPriority, "t3"); Thread t4 = new Thread(myPriority, "t4"); Thread t5 = new Thread(myPriority, "t5"); t2.setPriority(3); // 设置优先级 t3.setPriority(6); t4.setPriority(8); t5.setPriority(10); t1.start(); // 默认为5 t2.start(); t3.start(); t4.start(); t5.start(); } } class MyPriority implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority()); } }
package com.status; public class TestDaemon { public static void main(String[] args) { God god = new God(); You you = new You(); Thread t1 = new Thread(god); t1.setDaemon(true); // 设置为守护线程,默认收用户线程为false t1.start(); // 启动守护线程 new Thread(you).start(); // 启动用户线程 } } class God implements Runnable{ @Override public void run() { while (true){ // 虽然这里是死循环,但是用户线程结束后,该守护线程仍然会被JVM终止 System.out.println("有人在守候你"); } } } class You implements Runnable{ @Override public void run() { for (int i = 0; i <36500 ; i++) { System.out.println("开心度过短暂时光"); } System.out.println("Bye,the world. Game over."); } }