第七章 多线程


7.1、概述

进程:是正在运行的程序

线程:是进程中的单个顺序控制流,是一条执行路径

7.2、实现方式

7.2.1、方式一

class MyThread extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + ":" + i);
		}
	}
}

public class Main {
	public static void main(String[] args) {
		MyThread my1 = new MyThread();
		MyThread my2 = new MyThread();
		my1.setName("线程一");
		my2.setName("线程二");
		my1.start();
		my2.start();
	}
}

7.2.2、方式二

class MyRunnable implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}
}

public class Main {
	public static void main(String[] args) {
		MyRunnable my = new MyRunnable();
		Thread t1 = new Thread(my, "线程一");
		Thread t2 = new Thread(my, "线程二");
		t1.start();
		t2.start();
	}
}

7.3、线程优先级

class ThreadPriority extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + ":" + i);
		}
	}
}

public class Main {
	public static void main(String[] args) {
		ThreadPriority tp1 = new ThreadPriority();
		ThreadPriority tp2 = new ThreadPriority();
		ThreadPriority tp3 = new ThreadPriority();
		// 设置线程的名称
		tp1.setName("高铁");
		tp2.setName("飞机");
		tp3.setName("汽车");
		// 返回线程优先级
		System.out.println(tp1.getPriority());
		System.out.println(tp2.getPriority());
		System.out.println(tp3.getPriority());
		// 设置线程优先级
		tp1.setPriority(5);
		tp2.setPriority(10);
		tp3.setPriority(1);
		// 启动所有的线程
		tp1.start();
		tp2.start();
		tp3.start();
	}
}

7.4、线程的控制

sleep演示:使当前正在执行的线程停留(暂停执行)指定的毫秒数

class ThreadSleep extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + ":" + i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Main {
	public static void main(String[] args) {
		ThreadSleep ts1 = new ThreadSleep();
		ThreadSleep ts2 = new ThreadSleep();
		ThreadSleep ts3 = new ThreadSleep();
		ts1.setName("曹操");
		ts2.setName("刘备");
		ts3.setName("孙权");
		ts1.start();
		ts2.start();
		ts3.start();
	}
}

join演示:等待这个线程死亡才能执行其它线程

class ThreadJoin extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + ":" + i);
		}
	}
}

public class Main {
	public static void main(String[] args) {
		ThreadJoin tj1 = new ThreadJoin();
		ThreadJoin tj2 = new ThreadJoin();
		ThreadJoin tj3 = new ThreadJoin();
		tj1.setName("曹操");
		tj2.setName("刘备");
		tj3.setName("孙权");
		tj1.start();
		try {
			tj1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		tj2.start();
		tj3.start();
	}
}

Daemon演示:将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出

class ThreadDaemon extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(getName() + ":" + i);
		}
	}
}

public class Main {
	public static void main(String[] args) {
		ThreadDaemon td1 = new ThreadDaemon();
		ThreadDaemon td2 = new ThreadDaemon();
		td1.setName("关羽");
		td2.setName("张飞");
		// 设置主线程为刘备
		Thread.currentThread().setName("刘备");
		// 设置守护线程
		td1.setDaemon(true);
		td2.setDaemon(true);
		// 启动守护线程
		td1.start();
		td2.start();
		// 执行主线程的逻辑
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
		}
	}
}

7.5、线程的生命周期

image-20200718202343929

7.6、解决多线程数据安全问题

7.6.1、同步代码块

class SellTicket implements Runnable {
	private int tickets = 100;
	private Object obj = new Object();

	@Override
	public void run() {
		while (true) {
			synchronized (obj) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
					tickets--;
				}
			}
		}
	}
}

public class Main {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		t1.start();
		t2.start();
		t3.start();
	}
}

7.6.2、普通同步方法

class SellTicket implements Runnable {
	private int tickets = 100;

	@Override
	public void run() {
		while (true) {
			sellTicket();
		}
	}

	private synchronized void sellTicket() {
		if (tickets > 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
			tickets--;
		}
	}
}

public class Main {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		t1.start();
		t2.start();
		t3.start();
	}
}

7.6.3、静态同步方法

class SellTicket implements Runnable {
	private static int tickets = 100;

	@Override
	public void run() {
		while (true) {
			sellTicket();
		}
	}

	private static synchronized void sellTicket() {
		if (tickets > 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
			tickets--;
		}
	}
}

public class Main {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		t1.start();
		t2.start();
		t3.start();
	}
}

7.6.4、Look锁

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SellTicket implements Runnable {
	private int tickets = 100;
	private Lock lock = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			try {
				// 获得锁
				lock.lock();
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
					tickets--;
				}
			} finally {
				// 释放锁
				lock.unlock();
			}
		}
	}
}

public class Main {
	public static void main(String[] args) {
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st, "窗口1");
		Thread t2 = new Thread(st, "窗口2");
		Thread t3 = new Thread(st, "窗口3");
		t1.start();
		t2.start();
		t3.start();
	}
}

7.7、生产者和消费者模式

概述:生产者消费者模式是一个十分经典的多线程协作的模式,弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻。

演示:

class Box {
	// 定义一个成员变量,表示第几瓶牛奶
	private int milk;
	// 定义一个成员变量,表示奶箱的状态
	private boolean state = false;

	// 存储牛奶
	public synchronized void put(int milk) {
		// 如果有牛奶,等待消费
		if (state) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 如果没有牛奶,就生产牛奶
		this.milk = milk;
		System.out.println("送奶工送第" + this.milk + "瓶奶");
		// 生产完毕之后,修改奶箱状态
		state = true;
		// 唤醒其它等待的线程
		notifyAll();
	}

	// 获取牛奶
	public synchronized void get() {
		// 如果没有牛奶,等待生产
		if (!state) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 如果有牛奶,就消费牛奶
		System.out.println("用户拿到第" + this.milk + "瓶奶");
		// 消费完毕之后,修改奶箱状态
		state = false;
		// 唤醒其它等待的线程
		notifyAll();
	}
}

// 生产者
class Producer implements Runnable {
	private Box b;

	public Producer(Box b) {
		this.b = b;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 5; i++) {
			b.put(i);
		}
	}
}

// 消费者
class Customer implements Runnable {
	private Box b;

	public Customer(Box b) {
		this.b = b;
	}

	@Override
	public void run() {
		while (true) {
			b.get();
		}
	}
}

public class Main {
	public static void main(String[] args) {
		Box b = new Box();
		Producer p = new Producer(b);
		Customer c = new Customer(b);
		Thread t1 = new Thread(p);
		Thread t2 = new Thread(c);
		t1.start();
		t2.start();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_38490457/article/details/107494814