多线程
同步与异步
同步:排队执行,效率低但是安全
异步:同时执行,效率高但是数据不安全
并发与并行
并发:指两个或多个事件在同一个时间段内发生。
并行:指两个或多个事件在同一个时刻发生(同时发生)。
继承Thread
public class MyThread extends Thread{
public void run(){
//这里的代码,就是一条新的执行路径
//这个是执行路径的触发方式,不是调用run()方法,而是通过Thread对象的start()方法来启动任务
for (int i=1;i<10;i++){
System.out.println("白毛浮绿水"+i);
}
}
}
public class Demo {
public static void main(String[] args) {
MyThread m = new MyThread();
m.start();
for (int i=1;i<10;i++){
System.out.println("红掌拨清波"+i);
}
}
}![60197599423](C:\Users\ADMINI~1\AppData\Local\Temp\1601975994238.png)
实现Runnable
* 实现Runnable与继承Thread相比有如下优势
* 1.通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行相同任务的情况。
* 2.可以避免单继承所带来的局限性。
* 3.任务与线程是分离的,提高了程序的健壮性。
* 4.后续学习的线程池技术,接受Runnable类型的任务,不接受Thread类型的线程。
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println("一二三四五"+i);
}
}
}
public static void main(String[] args) {
//Runnable
MyRunnable m = new MyRunnable();
Thread t = new Thread(m);
t.start();
for (int i=0;i<10;i++){
System.out.println("五六七八九十"+i);
}
}
设置和获取线程名称
public class Demo3 {
public static void main(String[] args) {
//如何获取线程的名称
System.out.println(Thread.currentThread().getName());
new Thread(new MyRunnable(),"子线程").start();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
}
线程的休眠
for (int i=0;i<10;i++){
System.out.println(i);
//millis:毫秒 1000毫秒=1秒
Thread.sleep(1000);
}
线程中断
public class Demo4 {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start();
for (int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//给线程t1添加标记
t1.interrupt();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
for (int i=1;i<=10;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
System.out.println("发现中断标记,我们将这个线程自杀");
return;
}
}
}
}
}
守护线程
线程:分为守护线程和用户线程
用户线程:当一个进程不包括任何一个存活的用户线程时,进程结束
守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡。
把t1设置为守护线程,代码继线程中断的代码
t1.setDaemon(true);
线程安全1-同步代码块
public class Demo6 {
public static void main(String[] args) {
//线程安全问题
Runnable r = new Ticket();
new Thread(r,"a").start();
new Thread(r,"b").start();
new Thread(r,"c").start();
}
static class Ticket implements Runnable{
private int count = 10;
private Object o = new Object();
@Override
public void run() {
while (true){
synchronized (o){
if (count>0){
System.out.println("准备出票");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
}
else {
break;
}
}
}
}
}
}
线程安全2-同步方法
public class Demo7 {
public static void main(String[] args) {
//线程安全2-同步方法
Runnable r = new Ticket();
new Thread(r, "a").start();
new Thread(r, "b").start();
new Thread(r, "c").start();
}
static class Ticket implements Runnable {
private int count = 10;
@Override
public void run() {
while (true) {
boolean flag = sale();
if (!flag) {
break;
}
}
}
//在方法前加上synchronized
public synchronized boolean sale() {
if (count > 0) {
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count);
return true;
}
return false;
}
}
}
线程安全3-显示锁Lock
public class Demo8 {
public static void main(String[] args) {
//线程不安全
//线程安全3-显示锁Lock 子类 ReentrantLock
Runnable r = new Ticket();
new Thread(r, "a").start();
new Thread(r, "b").start();
new Thread(r, "c").start();
}
static class Ticket implements Runnable {
private int count = 10;
private Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
//锁住
l.lock();
if (count > 0) {
System.out.println("准备出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName() + "出票成功,余票:" + count);
} else {
break;
}
//解锁
l.unlock();
}
}
}
}
公平锁与非公平锁
//显示锁 l:fair参数为true 就表示是公平锁(排队)
private Lock l = new ReentrantLock(true);
线程死锁
public class Demo9 {
public static void main(String[] args) {
//线程死锁
Culprit c = new Culprit();
Police p = new Police();
MyThread m = new MyThread(c,p);
m.start();
c.say(p);
}
static class MyThread extends Thread{
private Culprit c;
private Police p;
public MyThread(Culprit c,Police p){
this.c = c;
this.p = p;
}
@Override
public void run() {
p.say(c);
}
}
//罪犯
static class Culprit{
public synchronized void say(Police p){
System.out.println("罪犯:你放过我,我放了人质。");
p.fun();
}
public synchronized void fun(){
System.out.println("警察放了罪犯,罪犯放了人质");
}
}
//警察
static class Police{
public synchronized void say(Culprit c){
System.out.println("警察:你放了人质,我放过你。");
c.fun();
}
public synchronized void fun(){
System.out.println("罪犯放了人质,警察放了罪犯");
}
}
}
生产者与消费者
package com.java.demo;
public class Demo10 {
/**
* 多线程通信问题,生产者与消费者问题
* @param args
*/
public static void main(String[] args) {
Food food =new Food();
new Cook(food).start();
new Waiter(food).start();
}
//厨师
static class Cook extends Thread{
private Food f;
public Cook(Food f) {
this.f = f;
}
@Override
public void run() {
for (int i=0;i<100;i++){
if(i%2==0){
f.setNameAndTaste("老干妈小米粥","香辣味");
}else {
f.setNameAndTaste("煎饼果子","甜辣味");
}
}
}
}
//服务生
static class Waiter extends Thread{
private Food f;
public Waiter(Food f) {
this.f = f;
}
@Override
public void run() {
for (int i=0;i<100;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
f.get();
}
}
}
static class Food{
private String name;
private String taste;
// true 表示可以生产
private Boolean flag = true;
public synchronized void setNameAndTaste(String name,String taste){
if (flag){
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
flag = false;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void get(){
if(!flag){
System.out.println("服务员端走的菜是:"+name+",味道:"+taste);
flag = true;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程的六种状态
线程可以处于以下状态之一:
NEW
尚未启动的线程处于此状态。
RUNNABLE
在Java虚拟机中执行的线程处于此状态。
BLOCKED
被阻塞等待监视器锁定的线程处于此状态。
WAITING
无限期等待另一个线程执行特定操作的线程处于此状态。
TIMED_WAITING
正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
TERMINATED
已退出的线程处于此状态。
带返回值的线程Callable
package com.java.demo;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo11 {
/**
* Callable线程
* @param args
*/
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Integer> c = new MyCallable();
FutureTask<Integer> task = new FutureTask<>(c);
new Thread(task).start();
//先运行子线程,得到子线程的返回值,再运行主线程
Integer A = task.get();
System.out.println(A);
for (int j=0;j<5;j++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+j);
}
}
static class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
for (int i=0;i<5;i++){
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+":"+i);
}
return 100;
}
}
}
缓存线程池
package com.java.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo12 {
/**
* 缓存线程池
* @param args
*/
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"汗滴禾下土");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"汗滴禾下土");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"汗滴禾下土");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"汗滴禾下土");
}
});
}
}
定长线程池
package com.java.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo13 {
/**
* 定长线程池
* @param args
*/
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"我想吃苹果");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"我想吃汉堡");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"我都想吃");
}
});
}
}
单线程线程池
package com.java.demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo14 {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午2");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午3");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午4");
}
});
}
}
周期任务 定长线程池
package com.java.demo;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Demo15 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
/**
* 1 定时延长一次
* 参数1:定时执行的任务
* 参数2:时常数字
* 参数3:时常数字的时间单位 TimeUnit的常量指定
*/
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("锄禾日当午");
}
},5, TimeUnit.SECONDS);
/**
* 周期性执行任务
* 参数1 任务
* 参数2 延迟时数字(第一次执行在什么时间以后)
* 参数3 周期时长数字(每隔多久执行一次)
* 参数4 时常的单位
*/
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("谁知盘中餐");
}
},5,1,TimeUnit.SECONDS);
}
}
Lambda表达式
package com.java.demo;
public class Demo16 {
public static void main(String[] args) {
print((int x, int y) -> {
return x+y;
}
,100,200);
}
public static void print(MyMath math,int x,int y){
int sum = math.sum(x,y);
System.out.println(sum);
}
static interface MyMath{
int sum(int x,int y);
}
}