多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
边吃饭边玩手机,边听歌边写作业
开黑打游戏
等等
进程: 是程序的一次执行,是动态的,一个进程至少包含一个线程,一个线程不能独立存在,它必须是进程的一部分;一个进程一直运行,直到所有非守护线程都结束运行后才能结束。
程序是代码段,是静态的。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
线程是独立的执行路径;
在程序运行时,即使没有自己的创建的线程,后台也会有多个线程,如主线程,gc线程;
main()为主线程,是程序的入口,用于执行整个程序;
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器由操作系统的调度算法决定,人为不可干涉;
对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
线程会带来额外的开销,如CPU调度的时间,并发控制的开销;
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致;
每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("MyThread is running!!! " + i); } } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); for (int i = 0; i < 1000; i++) { System.out.println("Main Thread is running " + i); } } }
public class RunnableDemo { public static void main(String[] args) { MyRunnable R1 = new MyRunnable("Thread-1"); R1.start(); MyRunnable R2 = new MyRunnable("Thread-2"); R2.start(); for (int i = 0; i < 3 ; i++) { System.out.println("这是主线程main"); } } } class MyRunnable implements Runnable { private Thread t; private String threadName; public MyRunnable(String name) { threadName = name; System.out.println("Creating: " + threadName); } @Override public void run() { System.out.println("Running: " + threadName ); try { for (int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + "," + i); Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread: " + threadName + "interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start() { System.out.println("Starting " + threadName); if (t == null) { t = new Thread(this, threadName); t.start(); } } }
使用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序star()这个线程。
当线程对象调用start()方法后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里的线程调度器的调度。
如果就绪队列中的线程获得了处理机,就可以执行run()方法此时线程便处于运行状态。
当一个线程执行了sleep(),suspend()等方法后,失去所占用资源之后,该线程就从运行态转化为阻塞态。在睡眠时间已到或获得设备资源后就可以重新进入就绪态。
阻塞态可以分为三种:
等待阻塞:运行态中的线程执行了wait()方法,使线程进入等待阻塞态
同步阻塞:线程在获取synchronized(同步)同步锁失败(因为同步锁被其他线程占用)。
其他阻塞:在调用线程的sleep()或join()发出的I/O请求时,线程会进入到阻塞态,当sleep()态超时,join()等待线程终止或超时时,或者I/O处理完毕,线程重新转入就绪态。
一个运行态的线程完成任务或其他终止条件发生时,该线程就切换到终止态;
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millisecond) | 在指定毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield | 暂停正在执行的线程对象,并执行其他线程 |
void interrupt() | 中段线程 |
boolean isAlive() | 检测线程是否处于活动状态 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxk0v3Ix-1623500327402)(https://i.loli.net/2020/11/16/R2PTzGVN5OAKUx8.png)]
代码演示:
// 1.建议线程正常停止 --> 利用次数, 不建议使用死循环 // 2.建议使用标准位来控制线程,让其自己停下来 // 3.不建议使用stop()和destroy() public class Stop implements Runnable { // 1.设置一个标志位 private boolean flag = true; @Override public void run() { int i = 0; while (this.flag) { System.out.println("Thread Running " + i++); } } // 2.设置一个公开的方法停止线程, 转换标志位 public void stop() { this.flag = false; } public static void main(String[] args) { Stop stop = new Stop(); new Thread(stop).start(); for (int i = 0; i < 1000; i++) { System.out.println("MainThread is running " + i); if (i == 666) { // 调用stop()方法切换标志位,让线程停止 stop.stop(); System.out.println("StopThread Stop, i = " + i); } } } }
代码演示:
import java.text.SimpleDateFormat; import java.util.Date; // sleep(millisecond)指定当前线程阻塞的毫秒数 // sleep存在异常(interruptException) // sleep完成后线程进入就绪状态 // sleep可以模拟网络延迟,倒计时等 // 每一个对象都有一个锁,sleep不会释放锁 // 利用线程控制来实现定时器 public class Timer { public static void main(String[] args) { Date starTime = new Date(System.currentTimeMillis()); while (true) { try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(starTime)); starTime = new Date(System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
代码演示:
public class TestYield { // 礼让线程,让当前正在执行的线程暂停,但不阻塞 // 将线程从运行状态转为就绪状态 public static void main(String[] args) { MyYield myYield = new MyYield(); new Thread(myYield, "Thread-A").start(); new Thread(myYield, "Thread-B").start(); } } class MyYield implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + " running"); Thread.yield(); // 线程礼让 System.out.println(Thread.currentThread().getName() + " be stopped"); } } /* 运行结果; Thread-A running Thread-A be stopped Thread-B running Thread-B be stopped */
代码演示:
public class TestJoin implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " Running " + i); } } public static void main(String[] args) throws InterruptedException { TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin, "testJoin"); thread.start(); for (int i = 0; i < 1000; i++) { if (i == 200) { thread.join(); } System.out.println("MainThread Running " + i); } } }
代码演示:
// 监视线程的状态 public class ThreadMonitor { public static void main(String[] args) { Thread thread = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Thread is running"); }); // 监视 Thread.State state = thread.getState(); System.out.println(state); thread.start(); state = thread.getState(); System.out.println(state); while (state != Thread.State.TERMINATED) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } state = thread.getState(); System.out.println(state); } } }
代码演示:
// 测试线程的优先级 // 范围: 1 - 10 // 默认为 5 public class TestPriority { public static void main(String[] args) { MyPriority myPriority = new MyPriority(); System.out.println(Thread.currentThread().getName() + " 的优先级为 " + Thread.currentThread().getPriority()); Thread thread_A = new Thread(myPriority, "thread_A"); Thread thread_B = new Thread(myPriority, "thread_B"); thread_B.setPriority(7); Thread thread_C = new Thread(myPriority, "thread_C"); thread_C.setPriority(10); Thread thread_D = new Thread(myPriority, "thread_D"); thread_D.setPriority(4); Thread thread_E = new Thread(myPriority, "thread_E"); thread_E.setPriority(1); thread_A.start(); thread_B.start(); thread_C.start(); thread_D.start(); thread_E.start(); } } class MyPriority implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + " 的优先级为 " + Thread.currentThread().getPriority()); } }
代码演示:
// 线程分为用户线程和守护线程 // 虚拟机必须确保用户线程执行完毕 // 虚拟机不必等待守护线程(内存监控, 垃圾回收, 操作日志记录等等)完毕 // 测试守护线程 public class TestDaemon { public static void main(String[] args) { God god_ = new God(); People people_ = new People(); Thread god = new Thread(god_, "God"); // 把God设置为守护线程 god.setDaemon(true); Thread people = new Thread(people_, "people"); god.start(); people.start(); } } class People implements Runnable { @Override public void run() { for (int i = 0; i < 3000; i++) { System.out.println(Thread.currentThread().getName() + " 活着 " + i); } System.out.println(Thread.currentThread().getName() + " 死亡"); } } class God implements Runnable { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + " 守护"); } } }
使用Lock,演示代码
import java.util.concurrent.locks.ReentrantLock; public class UnsafeThread01 { public static void main(String[] args) { Sale sale = new Sale(); Thread threadA = new Thread(sale, "APP"); Thread threadB = new Thread(sale, "官网"); Thread threadC = new Thread(sale, "票贩子"); threadA.start(); threadB.start(); threadC.start(); } } class Sale implements Runnable { // 票数 int ticketNums = 10; boolean flag = true; public final ReentrantLock lock = new ReentrantLock(); public void run() { buy(); } // 售票 public void buy() { while (flag) { try { lock.lock(); if (ticketNums <= 0) { flag = false; break; } Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " 卖出了第 " + ticketNums-- + " 张票"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } }
管程法:
package zl.Winter.Demo16_thread; // 测试生产者消费者模型 // 管程法 public class TestPC { public static void main(String[] args) { SynContainer container = new SynContainer(); Producer producer = new Producer(container); Costumer costumer = new Costumer(container); Thread thread_A = new Thread(producer,"生产者"); Thread thread_B = new Thread(costumer,"消费者"); thread_A.start(); thread_B.start(); } } // 生产者 class Producer implements Runnable { SynContainer container; public Producer(SynContainer container) { this.container = container; } // 生产 @Override public void run() { for (int i = 1; i < 100; i++) { container.push(new Chicken(i)); System.out.println("生产者生产了第" + i + "只鸡"); } } } // 消费者 class Costumer implements Runnable { SynContainer container; public Costumer(SynContainer container) { this.container = container; } // 消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费者消费了-->>第" + container.pop().id + "只鸡"); } } } // 产品 class Chicken { int id; public Chicken(int id) { this.id = id; } } // 缓冲区 class SynContainer { // 容器 Chicken[] chickens = new Chicken[10]; // 容器计数器 int count = 0; // 生产者放入产品 public synchronized void push(Chicken chicken) { // 容器满, 等待消费者消费 if (count == chickens.length) { // 通知消费者消费, 生产者等待 try{ this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } // 容器没满, 放入产品 chickens[count] = chicken; count++; // 通知消费者消费 this.notifyAll(); } // 消费者消费 public synchronized Chicken pop() { // 判断是否能消费 if (count == 0) { // 等待生产者生产, 消费者等待 try{ this.wait(); }catch(InterruptedException e){ e.printStackTrace(); } } // 可以消费,生产者消费 count--; Chicken chicken = chickens[count]; // 消费完毕, 通知生产者生产 this.notifyAll(); return chicken; } }
信号灯法:
// 测试生产者消费者模型 // 信号灯法 public class TestPC2 { public static void main(String[] args) { Cinema cinema = new Cinema(); new Player(cinema).start(); new Audience(cinema).start(); } } // 生产者 --> 演员 class Player extends Thread { Cinema cinema; public Player(Cinema cinema1){ this.cinema = cinema1; } @Override public void run() { for (int i = 0; i < 20; i++) { if(i%2 == 0){ this.cinema.play("<<大话西游>>"); }else{ this.cinema.play("广告: 你的益达"); } } } } // 消费者 --> 观众 class Audience extends Thread { Cinema cinema; public Audience(Cinema cinema1){ this.cinema = cinema1; } @Override public void run() { for (int i = 0; i < 20; i++) { this.cinema.watch(); } } } // 产品 --> 节目 class Cinema{ // 节目 String program; // 演员是否在表演 boolean flag = true; // 演员表演. 观众等待 public synchronized void play(String program){ if(!flag){ try{ this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println("表演了" + program); // 通知观众观看 this.program = program; this.flag = !this.flag; this.notifyAll(); } } // 观众观看, 演员等待 public synchronized void watch(){ if(flag){ try{ this.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println("观众观看了" + program); // 通知演员表演 this.flag = !this.flag; this.notifyAll(); } }