线程并发编程

1. 有几种新启线程的方式?

答案只有两种。我们来看看Thread的构造方法的形式,如下:

分析: 

方式一:查看Thread的构造函数一类型如下:

class Thread implements Runnable {} // 线程Thread实现了接口,即里面肯定自己已经实现run方法。

public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0); //第二个参数Runnale对象传入的为空
}

Thread.java 中的run 如下:
public void run() {
    if (target != null) {
        target.run();
    }
}

当调用无入参的Thread构造函数的时候,需要复写里面的run方法。

方式二,给Thread传一个Runnable对象,或者实现了Runnable接口的对象例如:FutureTask类型的对象
public Thread(Runnable target) { //其中的target,就是使用者必须要传入的 init(null, target, "Thread-" + nextThreadNum(), 0); }

注意:Thread.java中的run方法不就是一种回掉吗?

线程总共有6种状态。

1. 当线程的时间片用完了,或者被剥夺了,线程就会从运行态切换到就绪状态

2.使用显示锁Lock, Lock的底层是使用的是park()函数,这样线程处于的状态是等待或者等待超时状态,有且仅有synchronized的时候才是阻塞状态。等待是主动行为,阻塞是被动行为。

下面是通过thread.getstate()获取的线程在虚拟机中源码定义的状态,非线程在操作系统中的状态

注意:
* A thread can be in only one state at a given point in time.
* These states are virtual machine states which do not reflect
* any operating system thread states.

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

产生死锁的条件:

1.  互斥条件。 资源独享   2. 请求和保持   3.资源不能被剥夺  4.环路等待

 破锁方法:

1.强制改变拿资源的顺序。

2.拿到资源放手。 Lock接口就是这个作用。尝试拿锁。ReentrantLock

3. 复制资源,ThreadLocals 每个线程都独享资源。

在使用Lock的时候要避免出现活锁的现象,就是两个线程一个都是尝试,不断的尝试来耗费资源。这个时候就需要sleep一个随机数,等待一下让另一个线程可以有机会拿到自己的资源。sleep状态是不会释放锁的,所以需要将sleep放置在拿锁之外。

ThreadLocal学习。

如果这样处理: 做一个map, key :使用当前的线程,value存放值,这样线程是不再去争夺value资源了,但是会产生Map集合的竞争,这样又会出现不必需要的资源竞争

出于这个原因,JDK   设计思想是:

每个线程里面都含有一个 ThreadLocalMap ,这个是Thread线程里面的私有变量,

可以通过获取当前线程来获取这个Map的。这个Map的key是当前的ThreadLocal Value为设置的值。

2. 每个map里面再存放一个Entry[]数组,这个数组里面存放的都是一个个Entry对象,这个对象里面存放是的key:ThreadLocal ,Value是设置的值。

定义在类里面的static的类和外面的类是没有任何关系的,不会持有外部类的对象。完全相互独立。

CAS(Compare and swap)

什么是原子操作?

里面的操作要不全部一起执行,要不全部都不执行。这就是原子操作。

CAS原理:自己线程拿着值去比较,如果和自己拿的值一样的,就进行相关操作,如果不是,就拿着新值重新计算再来一次。

synchronized包含的一大坨操作全部都是原子操作,不可拆分。但是这个是重量级锁。

悲观锁:先拿锁,再操作。Lock和synchronized都是悲观锁。上下文切换耗时。

乐观锁: 拿到资源就比较重试比较,这种性能比悲观锁要好。

CAS 的缺点:

1.ABA原则   使用AtomicMarkableReference  AtomicStampedReference实现版本戳来解决ABA问题,每修改一次,就改一次版本。

2开销问题

Jdk中相关原子操作类的使用

更新基本类型类:AtomicBoolean,AtomicInteger,AtomicLong

更新数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray

更新引用类型:AtomicReference,AtomicMarkableReference,AtomicStampedReference

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值