目录
1.线程
1.1继承Thread类
package com.yg.thread;
/**
* 不推荐使用,
* 由于单继承的原因
*/
public class ThreadDemo extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--子线程");
}
}
public static void main(String[] args) {
ThreadDemo thread1 = new ThreadDemo();
thread1.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--主线程");
}
}
}
1.2实现Runnable接口
package com.yg.thread;
public class RunnableDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--子线程");
}
}
public static void main(String[] args) throws CloneNotSupportedException {
RunnableDemo thread2 = new RunnableDemo();
new Thread(thread2).start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--主线程");
}
}
}
1.3实现Callable接口
package com.yg.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableDemo implements Callable<Integer> {
@Override
public Integer call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "----》实现Callable");
}
return 100;
}
public static void main(String[] args) {
CallableDemo thread3 = new CallableDemo();
FutureTask<Integer> futureTask = new FutureTask<>(thread3);
new Thread(futureTask).start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--主线程");
}
Integer integer = null;
try {
//todo 获取返回值
integer = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("--------==========" + integer);
}
}
2.线程方法
2.1join线程
package com.yg.thread;
/**
* @author yuguang
* @date 2021/3/24 10:03
* @description 使用场景:某个任务是分阶段的,一个阶段任务完不成,不能进入下一个阶段。
*/
public class JoinThread extends Thread {
@Override
public void run() {
for (int i = 0; i <5; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
public static void main(String[] args) throws InterruptedException {
JoinThread t1 = new JoinThread();
JoinThread t2 = new JoinThread();
t2.start();
t2.join();
t1.start();
t1.join(); //todo 按照顺序排队执行,等待该线程死亡。
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
}
2.2后台线程-Daemon线程
package com.yg.thread;
/*
后台线程又叫Daemon线程,守护线程,精灵线程。
它的作用是运行于后台,为前台线程提供服务。当所有前台线程执行完毕,后台线程就死亡。
典型的垃圾回收线程就是 一条后台线程。
前台线程执行完毕,后台线程死亡之前还是有个时间差的,在这个时间内,后台线程还可能运行。
特点:
1、当非守护线程结束以后,程序就结束,Java程序退出,会杀死所有的守护线程。
2、所有守护线程不适合做一些访问固有资源,比如访问文件,访问数据库等操作,因为可能没执行完成就结束了。
*/
public class DaemonThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
public static void main(String[] args) throws InterruptedException {
DaemonThread t1 = new DaemonThread();
t1.setDaemon(true);
t1.start();
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
}
2.3.权重 Priority
package com.yg.thread;
/*
优先级的级别通常是从1~10的整数,但是不同操作系统有所不同,
建议你设置的时候用Thread.MAX_PRIORITY和Thread.MIN_PRIORITY。
设置高的优先级代表被线程调度器分配cpu的可能性越大。大多少?不可控。
*/
public class PriorityThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
public static void main(String[] args) throws InterruptedException {
PriorityThread t1 = new PriorityThread();
PriorityThread t2 = new PriorityThread();
//设置优先级只是建议线程调度器尽量先为线程分配cpu
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
t1.setPriority(Thread.MIN_PRIORITY);
t2.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "----" + i);
}
}
}
2.4.wait
package com.yg;
/**
* @author yuguang
* @date 2021/3/24 15:04
* @description
*/
public class WaitThread implements Runnable {
private Object obj = new Object();
@Override
public void run() {
synchronized (obj) {
obj.notify(); //唤醒
System.out.println("线程执行--开始");
try {
obj.wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程执行--结束");
}
}
public static void main(String[] args) throws InterruptedException {
WaitThread thread = new WaitThread();
new Thread(thread).start();
Thread.sleep(1000);
new Thread(thread).start();
}
}
2.5.Notify
package com.yg;
/**
* @author yuguang
* @date 2021/3/24 15:04
* @description
*/
public class NotifyThread implements Runnable {
private Object obj = new Object();
private Boolean flag = true;
public void setFlag(Boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag) {
testWait();
} else {
testNotify();
}
}
public void testWait() {
synchronized (obj) {
System.out.println("线程执行--开始");
try {
obj.wait(); //todo 唤醒之后向后继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程执行--结束");
}
}
public void testNotify() {
//todo 必须要加上同步锁,否则会报错:java.lang.IllegalMonitorStateException
synchronized (obj) {
obj.notify();
}
}
public static void main(String[] args) throws InterruptedException {
NotifyThread thread = new NotifyThread();
new Thread(thread).start();
//睡眠
Thread.sleep(2000);
thread.setFlag(false);
new Thread(thread).start();
}
}
3.例子
3.1.卖票-超卖-使用
-
如果去掉synchronized,会出现超卖问题
-
如果使用:synchronized方法 或者 synchronized代码块,超卖问题解决
/**
* 卖票、超卖了
* 1、线程同步,推荐使用同步方法
*
*/
public class SaleTickets {
private int tickets = 10;
//同步方法
/* public synchronized void sale() {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "--开始卖票--剩余:" + tickets);
tickets--;
System.out.println(Thread.currentThread().getName() + "--售票结束--剩余:" + tickets);
} else {
System.out.println(Thread.currentThread().getName() + "--无票了--剩余:" + tickets);
}
}*/
//卖票-同步代码块
public void sale() {
synchronized (this) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "--开始卖票--剩余:" + tickets);
tickets--;
System.out.println(Thread.currentThread().getName() + "--售票结束--剩余:" + tickets);
} else {
System.out.println(Thread.currentThread().getName() + "--无票了--剩余:" + tickets);
}
}
}
}
package com.yg.thread.demo;
/**
* 卖票、超卖了
*/
public class SaleTicketsThread extends Thread {
private SaleTickets saleTickets;
public SaleTicketsThread(SaleTickets saleTickets) {
this.saleTickets = saleTickets;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
saleTickets.sale();
}
}
public static void main(String[] args) {
SaleTickets tickets = new SaleTickets();
//共享一个票箱
SaleTicketsThread t1 = new SaleTicketsThread(tickets);
SaleTicketsThread t2 = new SaleTicketsThread(tickets);
SaleTicketsThread t3 = new SaleTicketsThread(tickets);
t2.start();
t3.start();
t1.start();
}
}
3.2生产者和消费者
商品
package com.yg.producer_consumer;
public class Goods {
private int id;//编号
private String name; //名称
public Goods(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
生产者
package com.yg.producer_consumer;
/**
* 生产者
*/
public class Producer implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}//一秒钟生产一个商品
synchronized (TestProducerConsumer.queue) {
if (TestProducerConsumer.queue.size() < TestProducerConsumer.MAX_GOODS) {
Goods goods = new Goods(1, "商品1");
TestProducerConsumer.queue.add(goods);
System.out.println(Thread.currentThread().getName() + "----生产了商品");
}else {
//货架满了,生产者休息
try {
TestProducerConsumer.queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
消费者
package com.yg.producer_consumer;
/**
* 消费者
*/
public class Consumer implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}//一秒钟 消费一个商品
synchronized (TestProducerConsumer.queue) {
//货架不为空就消费
if (!TestProducerConsumer.queue.isEmpty()) {
Goods poll = TestProducerConsumer.queue.poll();
System.out.println(Thread.currentThread().getName() + "---取出商品");
} else {
//todo 叫生产者生产
TestProducerConsumer.queue.notify();
}
}
}
}
}
测试
package com.yg.producer_consumer;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class TestProducerConsumer {
public static final int MAX_GOODS = 10; //商品
public static final int MAX_PRODUCER = 5; //生产者上线
public static final int MAX_CONSUMER = 4; //消费者上线
public static Queue<Goods> queue = new ArrayBlockingQueue<>(MAX_GOODS);//货架
public static void main(String[] args) {
Producer producer = new Producer();
Consumer consumer = new Consumer();
for (int i = 0; i < 5; i++) {
new Thread(producer, "生产者"+i).start();
}
for (int i = 0; i < 1; i++) {
new Thread(consumer, "消费者"+i).start();
}
}
}