java-多线程
多线程技术概述
线程和进程:
进程:
*是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间
线程:
*是进程中的一个执行路径,共享一个内存Jon关键,纤层之间可以自由切换,并发执行,一个进程最少有一个线程。
*线程实际上是在进程的基础之上的进一步划分,一个进程启动之后,里买的若干执行路径又可以划分为若干个线程
线程调度:
分时调度:
*所有线程轮流使用cpu的使用权,平均分配每个线程占用cpu的时间。
抢占式调度:
*优先让优先级高的线程使用cpu,如果线程的优先级相同,那么会随机选择一个(线程随机性),java使用
*cpu使用抢占式调度模式在多给线程之间进行着高速的切换,对于cpu的一个核心而言,某个时刻,只能执行一个线程,而cpu在多个线程之间的切换素的相对于我们的感觉要快,看上去就是在同一时刻同时运行,其实,多线程程序并不能提高程序的运行素的,但能够提高程序的运行效率,让cpu的使用率更高
同步与异步:
同步:排队执行,效率低但安全
异步:同时执行,效率高,但是数据不安全
并发与并行
并发:指两个或多个事件在同一时间段内发生
并行:值两个或多个时间在同一时刻发生(同时发生)。
多线程的实现方法:
1.通过继承Thread类,并重写run()方法,在main方法中初始化之后,通过调用strat()方法,来调用run()方法。
public class Demo3{
public static void main(String[] args){
Demo4 d = new Demo4();
t.start();
for (int i = 0;i<10;i++) {
System.out.println("汗滴禾下土"+i);
}
}
}
public class Demo4 extends Thread{
@Override
public void run() {
// 这里的代码就是一条新的执行路径
// 这个执行路径的触发方式,不是调用run方法,惹事通过thread对象的start()方法来启动
for (int i = 0;i<10;i++) {
System.out.println("锄禾日当午"+i);
}
}
}
2.通过实现Runnable接口,并在main方法中初始化该类、Thread类,将初始化的MyRunnable的变量名,传给初始化的Thread,创建进程,调用start()方法,进而执行run()方法。
public class Demo3{
public static void main(String[] args){
Demo4 d = new Demo4();
Thread t = new Thread(d);
t.start();
for (int i = 0;i<10;i++) {
System.out.println("汗滴禾下土"+i);
}
}
}
public class Demo4 implements Runnable{
@Override
public void run() {
// 这里的代码就是一条新的执行路径
// 这个执行路径的触发方式,不是调用run方法,惹事通过thread对象的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());
Thread t = new Thread(new Demo4());
t.setName("123");
t.start();
new Thread(new Demo4()).start();
new Thread(new Demo4()).start();
new Thread(new Demo4()).start();
new Thread(new Demo4()).start();
}
static class Demo4 extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
}
线程休眠sleep
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
for (int i = 0;i<10;i++) {
System.out.println(i);
Thread.sleep(1000);
}
}
}
线程阻塞:所有消耗时间的操作
线程不安全解决方案:
线程安全1-同步代码块(隐式锁)
线程安全了,但是效率降低了
格式: synchronized(锁对象){}
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
Runnable r = new ticket();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
static class ticket implements Runnable {
// 票数
private int n = 10;
private Object o = new Object();
@Override
public void run() {
while (n>0) {
synchronized (o) {
if (n > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("售票中");
n--;
System.out.println("出票成功,余票:" + Thread.currentThread().getName() + ":" + n);
}else {
break;
}
}
}
}
}
}
-
线程安全2-同步方法:(隐式锁)
通过锁住方法:
非静态 : this
静态 : 类名.classpublic class Demo3 {
public static void main(String[] args) throws InterruptedException { Runnable r = new ticket(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } static class ticket implements Runnable { private int n = 10; private Object o = new Object(); @Override public void run() { while (true) { boolean flag = sale(); if (!flag) { break; } } } public synchronized boolean sale() { if (n > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("售票中"); n--; System.out.println("出票成功,余票:" + Thread.currentThread().getName() + ":" + n); return true; } return false; } } }
-
显示锁
public class Demo3 {public static void main(String[] args) throws InterruptedException { Runnable r = new ticket(); new Thread(r).start(); new Thread(r).start(); new Thread(r).start(); } static class ticket implements Runnable { private int n = 10; private Object o = new Object(); private Lock l = new ReentrantLock();// 创建锁 @Override public void run() { while (true) { l.lock(); if (n > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("售票中"); n--; System.out.println("出票成功,余票:" + Thread.currentThread().getName() + ":" + n); }else break; } l.unlock(); } } }
-
公平锁和非公平锁
在初始化显示锁的时候:
private Lock l = new ReentrantLock(true);
参数默认为false,表示非公平锁,true为公平锁
线程死锁:
当锁在执行的时候,调用另一个锁的线程,两个锁都要对方的响应,就被锁住了
public class Demo3 {
public static void main(String[] args) {
Police p = new Police();
Culprit c = new Culprit();
new MyThread(c, p).start();
c.say(p);
}
static class MyThread extends Thread{
private Culprit zuifan;
private Police jingcha;
public MyThread(Culprit zuifan, Police jingcha){
this.jingcha = jingcha;
this.zuifan = zuifan;
}
@Override
public void run() {
jingcha.say(zuifan);
}
}
// 警察
static class Police {
public synchronized void say(Culprit zuifan) {
System.out.println("警察:你放了人质,我方你");
zuifan.fun();
}
public synchronized void fun() {
System.out.println("警察:人质救了,但罪犯跑了了,");
}
}
// 罪犯
static class Culprit {
public synchronized void say(Police jingcha) {
System.out.println("罪犯:你放了我,我方人质");
jingcha.fun();
}
public synchronized void fun() {
System.out.println("罪犯跑了,人质被救了");
}
}
}
多线程通信问题
public class Demo3 {
/**
* 多线程通信问题: 生产者和消费者的问题
* @param args
*/
public static void main(String[] args) {
Food f = new Food();
new Chref(f).start();
new Waiter(f).start();
}
// 厨师
static class Chref extends Thread{
private Food f;
public Chref(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 boolean flag = true;
private String name;
private String taste;
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
已退出的线程处于此状态。
线程池:
1. 创建线程
2. 创建任务
3. 执行任务
4. 关闭线程
缓存线程池
import java.util.concurrent.*;
/**
* @Author: 徐豪祥
* @Description:
* @Date Created in 2020-11-30 19:37
* @Modified By:
*/
public class Demo4 {
public static void main(String[] args){
// 向线程池中加入新的任务
ExecutorService service = Executors.newCachedThreadPool();
// 指挥线程池中执行新的任务
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
}
}
定长线程池 :
newFixedThreadPool(2); 参数位置填写有几个线程
import java.util.concurrent.*;
/**
* @Author: 徐豪祥
* @Description:
* @Date Created in 2020-11-30 19:37
* @Modified By:
*/
public class Demo4 {
public static void main(String[] args){
// 向线程池中加入新的任务
ExecutorService service = Executors.newFixedThreadPool(2);
// 指挥线程池中执行新的任务
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
}
}
单线程线程池 :
newSingleThreadExecutor(); 单线程线程池
import java.util.concurrent.*;
/**
* @Author: 徐豪祥
* @Description:
* @Date Created in 2020-11-30 19:37
* @Modified By:
*/
public class Demo4 {
public static void main(String[] args){
// 向线程池中加入新的任务
ExecutorService service = Executors.newSingleThreadExecutor();
// 指挥线程池中执行新的任务
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"锄禾日当午1");
}
});
}
}
定时线程池
/**
* // 定时执行一次
* 参数1.定时执行的任务
* 参数2.时长数字
* 参数3.时长数字的时间单位,TimeUnit的常量指定
*
*/
public static void main(String[] args){
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
service.schedule(new Runnable() {
@Override
public void run() { System.out.println("123456"); }
},5, TimeUnit.SECONDS);
周期定时线程池
/**
* 周期性执行任务
* 参数1.任务
* 参数2.延时时长(第一次执行在什么时间以后)
* 参数3.周期时长数字(每隔多久执行一次)
* 参数4.时长数字的单位
*/
public static void main(String[] args){
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("123");
}
},5,2,TimeUnit.SECONDS);
}
Lambda表达式:
定义一个匿名内部类,定义成接口类,只保留一个方法,在main方法中用到时,只需要保留参数部分和代码块
public class Demo4 {
/**
* Lambda表达式
* 函数式编程思想:
* 面向对象: 创建对象调用方法,解决问题
*/
/**
// 冗余的Runnable类
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("123123");
}
});
t.start();
*/
/**
// Lambda表达式
Thread t = new Thread(() -> System.out.println("123123"));
t.start();
*/
public static void main(String[] args) {
print((int x, int y) -> {
return x+y;
},100,200);
}
public static void print(MyMath m, int x, int y){
int num = m.sun(x, y);
System.out.println(num);
}
static interface MyMath{
int sun(int x, int y);
}
}