[Java并发编程之美]第1章 线程基础 附加知识笔记

1.2线程创建与运行

创建线程有三种方式:

  1. 继承Thread类并重写run方法;
  2. 实现Runnable接口的run方法,new Thread时将该类对象作为参数传入;
  3. 实现Callable接口的call方法,new FutureTask时将该类对象作为参数传入,再在new Thread时将FutureTask对象作为参数传入。

对于第二种方式,有两种写法:

  1. 按规矩先写实现Runnable的类,然后在主类中调用该类
  2. 将实现Runnable接口的部分写成匿名类的形式。

如果模拟多个线程抢占资源,想要模拟多线程访问共享变量出错的问题,只有第一种方式可以出现这种情况。

对于第二种方式,因为匿名内部类里边访问外部的变量,实际上都必须是final类型的变量,而final修饰的变量是线程安全的,因此也就模拟不出来出错的情况了。特别的,在JDK8中,第二种写法会自动在底层加上final修饰符(待验证)。所以,想要模拟多个线程访问共享变量的情况,不要使用匿名内部类。

为什么在匿名内部类中引用外部对象要加final修饰符?

因为在匿名内部类中引用的外部对象受到外部线程的作用域的制约有其特定的生命周期,以线程为例,当外部的变量生命周期已经完结之后,内部的线程还在运行,怎么样解决这个外部生命周期已经结束而在内部却需要继续使用呢,这个时候就需要在外部变量中添加final修饰符,其实内部匿名类使用的这个变量就是外部变量的一个“复制品”,即使外部变量生命周期已经结束,内部的“复制品“依然可用。

对于传参,使用Runnable方式,只能使用主线程里面被声明为final的变量

书中提及,“对于传参,使用Runnable方式,只能使用主线程里面被声明为final的变量”。由上,笔者认为应也是为了保证参数的线程安全。

参考链接

https://blog.csdn.net/qq_36129922/article/details/82883464
https://blog.csdn.net/weixin_40003295/article/details/81097783
https://zhidao.baidu.com/question/572436227.html

猜你喜欢

转载自www.cnblogs.com/coding-gaga/p/12381013.html