Java多线程
一、多线程的定义
多线程程序指的是一个程序中包含多个执行流
,它是实现并发机制的有效手段。多线程意味着一个程序的多个语句块同时执行,但是不等于多次启动一个程序。
二、进程与线程
- 进程:
电脑中时会有很多单独运行的程序,每个程序有一个独立的进程,而进程之间是相互独立存在的。 - 线程:
进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。
(java中的main方法也叫作主线程)
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1-n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
三、并发与并行
- 并行:是指两个程序各自运行,互不干扰。并行是同一时间发生的。
- 并发:交替执行的,同一时间,只有一个程序在执行。执行到一定时间之后,切换到另一个程序执行。实现多线程是采用一种并发执行机制。
并发的实现
:
开辟另外的栈。
这就是多线程的原理。多线程的本质是多个栈内存空间。
每开一个线程,实际是在JVM栈内存空间中开辟了一个新的栈内存空间。
main方法所在的线程叫做主线程,main方法是所有程序的入口
入口只有一个。也就是说主线程只有一个。
四、多线程的实现
- 一个类继承Thread类,重写run方法
class Thread1 extends Thread {
private String name;
public Thread1(String name) {
this.name=name;
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行 : " + i);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();
}
}
开启线程:
new 对象,然后调用Thread的start()方法。线程就会被开启。
记住不是调用run方法,run方法不需要手动调用,是依靠start方法来开启线程
然后,JVM自动调用run方法。
run() 不会启动线程,只是普通的调用方法而已。
start() 方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间。
- 编写一个类,实现 java.lang.Runnable 接口,实现run方法。
采用Runnable也是非常常见的一种,我们只需要重写run方法即可。
class Thread2 implements Runnable {
private String name;
public Thread2(String name) {
this.name=name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行 : " + i);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
new Thread(new Thread2("C")).start();
new Thread(new Thread2("D")).start();
}
}
五、多线程的应用
package com.myJava.Thread;
class Storage {//仓库类
private String name;//产品名称
private int max, num, no;//最大库存量,产品库存数,产品编号
public Storage(String name, int max) {
this.name = name;
this.max = max;
}
public synchronized void input() {//同步的生产(入仓)方法
while(num >= max) {//若产品数超过最大库存数
try {
wait();
}
catch (Exception e) {
e.printStackTrace();
}
}
num ++;
System.out.printf("生产%d号%s, 当前库存数:%d\n" , ++no, name, num);
notify();//通知消费
}
public synchronized void output() {//同步的消费(出仓)方法
while (num <= 0) {//若库存没有产品
try
{wait();
}
catch (Exception e) {
e.printStackTrace();
}
}
num--;
System.out.printf("消费%d号%s, 当前库存数:%d\n", no-num, name, num);
notify();//通知生产
}
public String getName() {
return this.name;
}
public int getMax() {
return this.max;
}
}
class Producer extends Thread {//生产者类
Storage store;
public Producer(Storage store) {
this.store = store;
}
public void run() {
for(int i = 0; i<10; i++) {
store.input();//调用同步生产方法
}
}
}
class Consumer extends Thread {//消费者类
Storage store;
public Consumer(Storage store) {
this.store = store;
}
public void run() {
for(int i = 0; i<10; i++) {
store.output();//调用同步消费方法
}
}
}
public class TestThread {
public static void main(String[] args) {
Storage store = new Storage("洗衣机", 4);//库存4台洗衣机仓库
System.out.println("构建最大库存量为"+store.getMax()+store.getName()+"仓库\n");
Producer producer = new Producer(store);//生产者
Consumer consumer = new Consumer(store);//消费者
producer.start();
consumer.start();
}
}
构建最大库存量为4洗衣机仓库
生产1号洗衣机, 当前库存数:1
生产2号洗衣机, 当前库存数:2
生产3号洗衣机, 当前库存数:3
生产4号洗衣机, 当前库存数:4
消费1号洗衣机, 当前库存数:3
消费2号洗衣机, 当前库存数:2
消费3号洗衣机, 当前库存数:1
消费4号洗衣机, 当前库存数:0
生产5号洗衣机, 当前库存数:1
生产6号洗衣机, 当前库存数:2
生产7号洗衣机, 当前库存数:3
生产8号洗衣机, 当前库存数:4
消费5号洗衣机, 当前库存数:3
消费6号洗衣机, 当前库存数:2
消费7号洗衣机, 当前库存数:1
消费8号洗衣机, 当前库存数:0
生产9号洗衣机, 当前库存数:1
生产10号洗衣机, 当前库存数:2
消费9号洗衣机, 当前库存数:1
消费10号洗衣机, 当前库存数:0