如何创建线程?如何保证线程安全?
创建线程的方式一:继承Thread类(由于Java单继承的特性,这种方式用的比较少)
步骤:
1、继承Thread类,然后重写run方法
2、创建子类对象,然后调用start()方法来启动线程
我们可以看到这边现在只创建了一个线程,那么如果要创建多个线程要怎么做呢?通过继承Thread的方式创建线程,想要创建多个不同的线程就要先创建多个不同的继承Thread的类,然后再根据上面的步骤1,2来创建线程,这显然有些麻烦,为了展示多线程,我们先在上面的线程中增加一个主线程,也就是main方法中执行的线程。如下:
创建线程的方式二:实现Runnable接口(Java可以实现多个接口,这种方式常用)
步骤:
1、创建一个类实现Runnable接口,然后重写run方法
2、创建实现类对象、代理类对象,然后代理类对象调用start()方法启动线程
用实现Runnable接口的方式,实现多线程:
《模拟抢票系统》,代码如下:
线程调用了start()方法,并不意味着立即执行,而是到就绪状态,等待cpu的调度,所以每次执行的结果都是不一样的。
创建线程的方式三:实现java.util.concurrent并发包下的Callable接口(进阶版,初学者做个了解)
步骤:
1、创建一个类实现Callable接口,然后重写call()方法
(和run方法不一样的是,call方法可以有返回值,并且可以抛出异常)
2、创建Callable的实现类对象--》创建执行服务--》提交执行服务得到Future对象--》获取结果--》停止服务
2021-12-19 · 学动漫、设计、电竞、电商、短视频、软件等
一个类要想线程安全,除了上一篇文章通过外部解决方式外,还可以通过合理的设计类的内部来解决,使类本身就线程安全,那么要怎么才能使类是线程安全的呢?
类不是线程安全的原因主要就是它包含了一些属性,这些属性是这个类实例对象的变量,这些变量影响着对象状态,由于对这些属性的访问在多线程情况下出现一些不安全使得对象状态并不符合预期导致类的不安全,所以设计线程安全类大概方向就是保证这些影响对象状态的变量,在Java并发编程实战中的总结如下:
找出构成对象状态的所有变量;
找出约束状态变量的不变性条件;
建立对象状态的并发访问管理策略;
这里先解释下不变性条件,在一些类的它的一些变量的变化是有一定规则的,比如类中定义一个属性表示苹果卖出了多少斤,卖出就增加,退货就减少,但是它肯定不会是一个负值,不为负值这就是这个变量的不变性条件。在比如类中定义了最大值与最小值,那么在这两个变量只有有一个不变性条件就是最大值要大于等于最小值。
简单解释了不变性条件再来理解下上面3条:可以把这3条分成3个步骤,首先是找出构成对象状态的所有变量,第二步是找出变量的约束条件,最后是上面两步找出的变量进行并发访问控制保证不变性条件的约束,对比较独立的属性直接进行并发访问,但是对有关联的那就必须要更多的机制保证这个约束。
所以我们可以把设计线程安全的类步骤分成以下三块:
1、找出所有需要同步的属性,保证不可变条件和后验条件(方法执行后必须为真的条件),比如上面举的卖出苹果的重量,比如最大值与最小值关系;
2、保证一些依赖一些状态的操作正确执行(先验条件方法执行前必须为真的条件),比如单例模式中实体为null的时候才初始化;
3、一定要控制这些属性的所有权,基础类型的属性可能比较好控制,有些是引用类型但又要保证线程安全的,那就要严格控制所有权,否则有可能其他线程拿到这个引用进行修改这个对象的内容,造成线程不安全;
已有对象如何保证线程安全
我们可以设计出线程安全的类,但是有可能有些对象已经存在,然后它并不是线程安全,现在却需要保证它的线程安全,那该如何做呢?
通过监视器模式实现,把对象封装到一个新对象里面,所有对这个对象的访问都通过新对象的方法访问,然后保证新对象的方法是线程安全的就行了。
并不一定需要自己实现线程安全
但是有时候我们并不是一定要设计成线程安全的类,如果已经存在一些线程安全的类可以保证我们需要的线程安全,还是要尽量用现有的,比如上面提到过苹果卖出的重量,就可以利用AtomicInteger来保证安全,再比如一些缓存也可以用ConcurrentMap来保证线程安全,把我们需要保证的线程安全委托给一些线程安全的类。
但是委托并不是一定有用的,比如前面的最大、最小值例子,如果定义成现AtomicInteger也无法保证它们的不可变条件的约束!这种可能就只能加锁了,但是如果他们两个并没有不可变条件约束是两个无关的共享变量,还是可以把多个无关的状态变量委托给线程安全的类。
如何扩展线程安全类
那么如果一个线程安全的类功能不满足我们的需求,需要扩展一些功能,可是又不能修改这个类,那么就必须要对这个类进行扩展,扩展分两种方法继承、客户端扩展。继承实现比较简单,继承的类只要在保证新增的方法是线程安全的,那么它整个都是线程安全的,不过客户端扩展可能情况复杂一点.
2021-12-19 · 百度认证:河南新华电脑学院有限公司官方账号
2.绝对线程安全 绝对的线程安全完全满足Brian GoetZ给出的线程安全的定义,这个定义...
3.相对线程安全 相对线程安全就是我们通常意义上所讲的一个类是“线程安全”的。 它需要保证对...
4.线程兼容 线程兼容就是我们通常意义上所讲的一个类不是线程安全的。 线程兼容是指对象本身并...
创建多线程程序的第二种方式:实现Runnable接口。一般说来,确保线程安全的方法有这几个:竞争与原子操作、同步与锁、可重入、过度优化。