进程:是指一个内存中运行的程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程。
线程:进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。【java默认有两个线程:main、GC】
进程与线程的区别:
多线程(multithreading)【百科】:是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理“。
/** * 继承Thread 类 * 注意: 线程开启不一定立即执行,由CPU调度执行 */public class TestThread extends Thread{ @Override public void run() { // run的方法体 for (int i = 0; i < 2000; i++) { System.out.println("我在刷抖音!" + i); } } public static void main(String[] args) { TestThread thread = new TestThread(); thread.start(); for (int i = 0; i < 2000; i++) { System.out.println("我在上厕所!" + i); } }}
/** * 实现Runnable 接口 */public class TestRunnable implements Runnable { @Override public void run() { // run的方法体 for (int i = 0; i < 2000; i++) { System.out.println("我在刷抖音!" + i); } } public static void main(String[] args) { Thread thread = new Thread(new TestRunnable()); thread.start(); for (int i = 0; i < 2000; i++) { System.out.println("我在上厕所!" + i); } }}
/** * 实现Callable 接口 * * 好处: 1.可以定义返回值类型 2、可以抛出异常 */public class TestCallable implements Callable<Boolean> { String name = null; public TestCallable(String name){ this.name = name; } @Override public Boolean call() throws Exception { // run的方法体 for (int i = 1; i <= 20; i++) { System.out.println(name + i); } return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { // 1.创建线程 TestCallable t1 = new TestCallable("睡觉!"); TestCallable t2 = new TestCallable("水饺"); // 2.创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(2); // 3.提交执行 Future<Boolean> r1 = ser.submit(t1); Future<Boolean> r2 = ser.submit(t2); // 4.获取结果 Boolean res1 = r1.get(); Boolean res2 = r2.get(); System.out.println(res1); System.out.println(res2); // 5.关闭服务 ser.shutdown(); }}
后续章节补充
线程分为守护线程和用户线程,守护线程的作用是为其他线程运行提供便利服务,用户线程如果全部退出执行,守护线程也会随之关闭,守护线程最经典的 例子GC(垃圾回收器)。
/** * 守护线程*/public class TestDaemon { public static void main(String[] args) { Mom mom = new Mom(); Thread thread = new Thread(mom); thread.setDaemon(true); // 开启守护线程 thread.start(); new Thread(new Me()).start(); }} class Mom implements Runnable { @Override public void run() { while (true){ System.out.println("妈妈监视我写作业!!"); } }} class Me implements Runnable { @Override public void run() { for (int i = 0; i < 300; i++) { System.out.println("我在写作业!!"); } System.out.println("===》我作业写完了!!"); }}
JOIN合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。
/** * 线程插队 JOIN() */public class TestJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 200; i++) { 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 < 1000; i++) { if (i == 500){ thread.join(); // 插队 } System.out.println("main" +i); } }}
线程的优先级越高意味着获得调度的概率就高,但并不代表优先级低的线程就不会被调度,这都是看CPU心情的!!
/** * 线程优先级 * 线程默认的优先级 5 最大是 10 最小 1 * 线程设置优先级,要在线程启动前设置 */public class TestPriority implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority()); } public static void main(String[] args) { // 主线程的默认优先级 System.out.println(Thread.currentThread().getName() + "====>" + Thread.currentThread().getPriority()); TestPriority testPriority = new TestPriority(); Thread t1 = new Thread(testPriority, "t1"); Thread t2 = new Thread(testPriority, "t2"); Thread t3 = new Thread(testPriority, "t3"); // 设置优先级3 t1.setPriority(3); t1.start(); // 设置最大优先级 t2.setPriority(Thread.MAX_PRIORITY); t2.start(); // 设置最小优先级 t3.setPriority(Thread.MIN_PRIORITY); t3.start(); }}
案例:
/** * 线程睡眠 : 更容易发现多线程下方法存在的问题 (放大问题的发生性) */public class TestSleep implements Runnable{ int ticket = 10; @Override public void run() { while (true){ if (ticket <= 0 ){ break; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "抢到了第" + ticket-- + "票"); } } public static void main(String[] args) { TestSleep ticket = new TestSleep(); // 模拟三条线程同时抢票 new Thread(ticket,"小明").start(); new Thread(ticket,"小强").start(); new Thread(ticket,"黄牛").start(); }}
Java中对于线程总共设定了5个状态,分别为:新建状态、就绪状态、运行状态、阻塞状态、死亡状态。
导致线程阻塞主要有三种情况: