1.概念与引入
进程:操作系统上应用程序拆分成多个小任务
线程:进程拆分成对个小任务
在某个时刻,CPU的某个核中只能执行一个进程,进程可以拆分成多个线程,CPU的某个核中只能执行一个线程。CPU会轮换线程执行。
2.多线程的好处
线程要么和CPU进制交互,要么和硬件进行交互,当线程和硬件进交互时,CPU处于空闲时间。为了提高CPU利用率(理论上可以是100%)引入多线程。
3.创建多线程方式
1.继承Thread类重写run方法(线程执行任务信息),创建对象调用Thread类里start方法来开启线程
packagecn.tedu.thread;
public class ThreadDemo{
public static void main(String[]args){
//创建描述线程执行信息的类的对象
TDemo t=new TDemo();
//调用父类start方法来开启线程
//线程不会回头执行
t.start();
//主线程
for(int i=20;i>=0;i--){
System.out.println("main:"+i);
//休眠
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//定义类---代表线程的任务信息
//类与类之间是单继承,影响继承别的类
class TDemo extends Thread{
//重写run方法---存放线程执行的任务信息
@Override
public void run(){
//
for(int i=0;i<=20;i++){
System.out.println("run:"+i);
//线程休眠
try{
//休眠10毫秒
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
2.实现Runnable接口重写run方法(线程执行任务信息),由Runnable实现类对象来构建Thread类的对象来调用start方法开始线程(常用)
package cn.tedu.thread;
public class RunnableDemo{
public static void main(String[]args){
//创建代表线程执行信息的类的对象
RDemo r=new RDemo();
//创建Thread类对象
//Thread类和RDemo类都是Runnable的实现类
//同类对象给本类对象增强功能---装饰者设计模式
Thread t=new Thread(r);
//调用start方法
t.start();//开启线程
//主线程
for(int i=20;i>=0;i--){
System.out.println("main:"+i);
//休眠
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//定义类---代表线程执行任务信息
//类与接口是多实现,不影响实现别的接口
class RDemo implements Runnable{
//重写方法---线程执行任务信息
@Override
public void run(){
//
for(int i=0;i<=20;i++){
System.out.println("run:"+i);
//休眠
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
多线程之间存在相互抢占(CPU执行权—随机),抢占发生在代码的每一步,产生错误的数据问题,导致多线程数据并发安全问题
4.解决方式—加锁
1.同步代码块锁
synchronized(锁对象){}
根据锁对象共享进来的线程对象保证在执行代码块内容时不会有抢占
锁对象:一个对象,可以把哪些线程对象共享进来
可以把当前参与的线程对象共享进来的对象
方法区资源(把所有的线程对象都共享)
this(当参与的所有线程对象被Runnable实现类对象共享)
package cn.tedu.thread;
import java.io.FileInputStream;
imp