线程:线程是操作系统能够进行运算调度的最小单位 被包含在进程当中 是进程中的实际运作单位
并发:在同一时刻,有多个指令在单个CPU上交替执行
并行:在同一时刻,有多个指令在多个CPU上同时执行
多线程实现的三种方式
1 继承Thread类
package com.qcby.MyThread01;
public class MyThread extends Thread{
public void run(){
for(int i=0;i<100;i++){
System.out.println("Hello World");
}
}
}
package com.qcby.MyThread01;
import com.qcby.MyThread01.MyThread;
public class ThreadDemo {
/*
多线程第一种定义方式
1 自己定义一个类继承Thread
2 重写run方法
3 创建子类的对象 并启动线程
*/
public static void main(String[] arges){
MyThread p=new MyThread();
p.start();
}
}
2 实现Runnable接口
package com.qcby.Mythread02;
public class MyRun implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println("Hello");
}
}
}
package com.qcby.Mythread02;
public class ThreadDemo {
/*
1 自己定义一个类 实现Runnable接口
2 重写里面的run方法
3 创建自己的类的对象
4 创建一个Thread对象 并开启线程
*/
public static void main(String[] args) {
MyRun p=new MyRun();
Thread t=new Thread(p);
t.start();
}
}
3 实现Callable接口
package com.qcby.MyThread0;
import java.util.concurrent.Callable;
public class ThreadDemo implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for(int i=0;i<100;i++) {
sum+=i;
}
return sum;
}
}
package com.qcby.MyThread0;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyThread {
/*
1创建一个Callable类实现Callable接口
2 重写call(有返回值的 表示多线程运行结果)
3 创建Callable的对象(表示多线程要执行的任务)
4 创建FutureTask的对象(作用管理多线程运行的结果)
5 创建Thread对象 并启动
*/
public static void main(String[] args) throws ExecutionException, InterruptedException {
//表示多线程要执行的任务
ThreadDemo mc=new ThreadDemo();
//作用管理多线程运行的结果
FutureTask<Integer> f=new FutureTask<>(mc);
//创建线程对象
Thread p=new Thread(f);
p.start();
System.out.println(f.get());
}
}
三种方式的对比
常见的成员方法
线程的声明周期
同步代码块:
格式 synchronized(锁){
操作共享数据的代码
}
特点1 锁默认打开 有一个线程进去了 锁自动关闭
特点2 里面的代码全部执行完毕 线程出来后 锁自动打开
Lock锁:
JDK5以后提供 实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock是接口 不能直接实例化 采用它的实现类 ReentrantLock来定义实例化
等待唤醒机制:生产者消费者模式是一个十分经典的多线程协作的模式
案例
package com.qcby.MyThread03;
public class Foodie extends Thread{
@Override
public void run(){
while (true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
if(Desk.FoodFlag!=0){
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("厨师做了一碗面条");
Desk.FoodFlag=1;
Desk.lock.notifyAll();
}
}
}
}
}
}
package com.qcby.MyThread03;
import sun.security.krb5.internal.crypto.Des;
import java.time.DayOfWeek;
public class Cook extends Thread{
@Override
public void run(){
/*
1 循环
2 同步代码块
3 判断共享数据是否到了末尾(到了末尾)
4 判断共享数据是否到了末尾(没有)
*/
while (true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
if(Desk.FoodFlag==0){
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
Desk.count--;
System.out.println("吃货还能再吃面条"+ Desk.count+"碗!!");
Desk.lock.notifyAll();
Desk.FoodFlag=0;
}
}
}
}
}
}
Desk类用来控制生产者和消费者执行的代码
package com.qcby.MyThread03;
public class Desk {
/*
控制生产者 消费者的执行
*/
// 0代表还没有做出来 1代表做出来的饭菜
public static int FoodFlag=0;
//总个数
public static int count=10;
//锁对象
public static Object lock=new Object();
}
线程的运行
package com.qcby.MyThread03;
public class ThreadDemo {
public static void main(String[] args) {
Cook c=new Cook();
Foodie f=new Foodie();
c.setName("厨师");
f.setName("吃货");
c.start();
f.start();
}
}
等待唤醒机制第二种实现方式:阻塞队列
注意 put() take()方法的底层实现 自动实现锁的功能了
package com.qcby.MyThread04;
import java.util.concurrent.ArrayBlockingQueue;
public class Cook extends Thread{
ArrayBlockingQueue<String> queue;
public Cook(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while(true){
try {
queue.put("面条");
System.out.println("厨师放了一碗面条");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.qcby.MyThread04;
import java.util.concurrent.ArrayBlockingQueue;
public class Foodie extends Thread{
ArrayBlockingQueue<String> queue;
public Foodie(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while(true){
try {
String food=queue.take();
System.out.println("吃货拿走了"+food);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程实现代码
package com.qcby.MyThread04;
import java.util.concurrent.ArrayBlockingQueue;
public class ThreadDemo {
public static void main(String[] args) {
ArrayBlockingQueue<String> queue=new ArrayBlockingQueue<>(1);
Cook c=new Cook(queue);
Foodie f=new Foodie(queue);
c.start();
f.start();
}
}
线程的状态
线程池
案例
package com.qcby.ThreadPool;
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
package com.qcby.ThreadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadDemo {
public static void main(String[] args) {
//获取线程池对象
ExecutorService pool1=Executors.newCachedThreadPool(); //无上限的线程池
//提交任务
pool1.submit(new MyRunnable());
pool1.submit(new MyRunnable());
pool1.submit(new MyRunnable());
//销毁线程池
pool1.shutdown();
}
}