[2022.11.7]线程
线程就是独立的执行路径;
在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
main()称之为主线程,为系统的入口,用于执行整个程序;
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为的干预的。
对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
线程会带来额外的开销,如cpu调度时间,并发控制开销。
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
线程的创建有两种方式:
方式一:继承Thread类,重写run()方法,调用start开启线程
public class testdemo1 extends Thread {
@Override
public void run(){
//run方法线程体
System.out.println("1");
}
public static void main(String[] args) {
//main线程是主线程
//创建一个线程对象
testdemo1 demo1=new testdemo1();
//调用start()方法开启线程
demo1.start();
System.out.println("2");
}
}
这里线程的执行顺序并不是按照我们 执行start()的顺序,因为start()方法,并不是代表立即去执行线程,只不过是告诉cpu我可以被调度,至于它先执行哪个线程,要靠cpu去决定。(但是我们可以设置一个优先级,优先级高的显被执行的概率大,但是不是绝对的)
继承Thread类
子类继承Thread类具备多线程能力
启动线程:子类对象. start()
不建议使用:避免OOP单继承局限性
方式二:实现Runable接口,重写Run方法,执行线程需要丢入runnable接口实现类,调用start方法。
public class testdemo2 implements Runnable{
@Override
public void run(){
//run方法线程体
System.out.println("1");
}
public static void main(String[] args) {
//创建runnbale接口的实现类对象
testdemo2 demo2=new testdemo2();
Thread th=new Thread(demo2);
th.start();
System.out.println("2");
}
}
通过Thread的构造方法传入Runnable接口的实现类,然后执行start()方法,开启线程,相对于第一种方式,这里的Thread其实就是个静态代理对象。
实现Runnable接口
实现接口Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用