Java多线程

    并行针对进程,是多个进程同时执行.
    并发针对线程,是多个线程不停的切换执行,看起来像同时执行.

实现方式:

  1. 实现Runnable接口,重写run()方法;
            推荐,优点:资源共享,避免单继承限制,避免线程池不能放入Thread类问题.
  2. 继承Thread类,重写run()方法;
  3. 实现Callable接口,并与Future、ExecutorService结合使用.

状态:

  • 新建状态(New):New一个线程对象.
  • 就绪状态(Runnable):线程对象调用start()方法后.
  • 运行状态(Running):获取到CPU资源,执行run()方法.
  • 阻塞状态(Blocked):失去CPU资源.
  1. 一般阻塞:调用sleep()方法或其他线程join();
                sleep()结束或join()的线程结束,会重新进入就绪状态.
                sleep不会释放同步锁.
  2. 同步阻塞:获取同步锁失败;
                获取同步锁成功后进入就绪状态.
                同步锁池是顺序执行,先到先得.
  3. 等待阻塞:调用wait()方法;
                再调用notify()方法或notifyAll()方法进入同步阻塞.
                wait会释放同步锁.
                调用notify()方法不一定会唤醒到需要的线程对象,它是随机唤醒一个在对象锁上wait的线程.
                wait(),notify(),notifyAll()只能在synchronized修饰中调用.
  • 死亡状态(Dead):run()结束或异常退出.

控制:

    t.start():调用线程进入就绪状态.
    Thread.yield():当前线程释放CPU资源,回到就绪状态.
    Thread.sleep(long millis):当前线程休眠对应时间,进入一般阻塞,sleep时间结束回到就绪状态,不会释放同步锁.
    t.join():强制执行调用线程,当前线程进入一般阻塞,强制执行线程结束或终止,当前线程回到就绪状态.
        t.join(long millis):强制执行调用线程,当前线程进入一般阻塞,强制执行线程结束或终止或超时,当前线程回到就绪状态,如超时,调用线程进入等待阻塞.
    o.wait():当前线程进入等待阻塞,会释放同步锁(锁对象o).只能在synchronized修饰中调用.
        o.wait(long millis):相当于wait()对应时间结束后直接notify().
    o.notify():随机唤醒一个在对应对象锁(锁对象o)上wait()的一个线程,进入同步阻塞.只能在synchronized修饰中调用.
        o.notifyAll():唤醒所有在对应对象锁(锁对象o)上wait()的线程,进入同步阻塞.只能在synchronized修饰中调用.
    t.interrupt():标记调用线程为中断状态,当其为一般阻塞或等待阻塞状态时,立即抛出InterruptedException.
        Thread.interrupted():判断当前线程的中断状态,同时清除中断标记.
        t.isInterrupted():判断调用线程的中断状态,不清除中断标记.
    stop()(废弃):不能保证操作原子性,造成数据不完整.
    suspend()(废弃):不释放锁,容易造成死锁.
    resume()(废弃)

常用方法:

    Thread.currentThread():获取当前线程实例.
    Thread.activeCount():获取当前进程中存活的线程数.
    t.isAlive():判断调用线程是否存活.
    t.setName(String name):设置调用线程名称.
    t.isDaemon():判断调用线程是否是守护线程.
    t.setDaemon(boolean on):设置调用线程是否为守护线程.
    t.setPriority(int newPriority):设置调用线程优先级.
    t.getPriority():获取调用线程优先级.

同步:

    1.synchronized关键字:
        被synchronized修饰的代码具有可见性和原子性.synchronized是公平锁,悲观锁.
        1.synchronized修饰块:

synchronized(object){ 
	
}

            作用域:
                object为同步锁对象,即作用域.当没有明确的object作为锁,只是为了让一段代码同步,推荐用lock(private byte[] lock=new byte[0];)作为锁对象,最为节省资源.
                当object为this时,作用域为当前类的实例.
                当object为Object.class(Object为当前类)时,作用域为当前类的所有实例.
        2.synchronized修饰方法:

public (static) void synchronized method(){

}

            作用域:
                当修饰非静态方法时,作用域为当前实例.相当于锁对象为this的同步块.
                当修饰静态方法时,作用域为当前类的所有实例.相当于锁对象为Object.class(Object为当前类)的同步块.
        与ReentrantLock相比更为便捷.

    2.ReentrantLock(重入锁):
        可重复申请的锁,申请锁X次,释放锁也要X次.
        公平锁与非公平锁:
            非公平锁:
                ReentrantLock lock=new ReentrantLock(false);
                抢锁机制,先申请不一定先获得.
                ReentrantLock默认构造方法为非公平锁.
            公平锁:
                ReentrantLock lock=new ReentrantLock(true);
                顺序执行,先申请先获得.
        申请锁方法:
            lock.lock():申请锁,失败就等待锁.
                使用方式:

ReentrantLock lock=new ReentrantLock();	
public void method(){
	lock.lock();
	try{
		
	}finally{
		lock.unlock();
	}
}

            lock.tryLock():尝试申请锁,成功返回true,失败返回false,不等待锁.
            lock.tryLock(long timeout,TimeUnit unit):限定时间内尝试申请锁,成功返回true,失败就等待锁对应时间,超时返回false.
                使用方式:

ReentrantLock lock=new ReentrantLock();	
public void method(){
	if(lock.tryLock()){//lock.tryLock(3,TimeUnit.SECONDS);
		
	}
	try{
		
	}finally{
		if(lock.isHeldByCurrentThread()){//判断当前线程是否持有该锁
			lock.unlock();
		}
	}
}

            lock.lockInterruptibly():申请可中断锁,类似lock(),但是等待锁时可以被中断(通过t.interrupt()),中断时抛出InterruptedException.
        常用方法:
            isFair():是否是公平锁.
            isLocked():是否被线程获取.
            hasQueuedThreads():是否有线程在等待此锁.
            hasQueuedThread(Thread t):线程t是否在等待此锁.
            getQueueLength():等待此锁的线程数.
            hasWaiters(Condition c):是否有线程在c上await().
            getWaitQueueLength(Condition c):在c上await()的线程数.
            isHeldByCurrentThread():当前线程是否获取到锁.
            getHoldCount():当前线程申请锁次数,即此线程执行lock()次数.
        Condition:
            ReentrantLock提供了类似于synchronized的wait()和notify()的机制,通过创建Condition对象来实现.
            Condition condition=lock.newCondition();
            控制:
                condition.await():等效于于wait().
                condition.signal():类似于notify(),区别在于其是唤醒在对应condition对象await()的线程,不是随机唤醒一个.
                condition.signalAll():等效于于notifyAll().
            和synchronized类似,使用以上方法必须在获取到锁之后.
        扩展:
            ReentrantReadWriteLock(读写锁):
                读写锁和重入锁类似,用法基本一致,区别在于读写锁分两种状态,读锁和写锁,读读共享,读写互斥,写写互斥.而重入锁完全互斥.
                使用方式:

ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void read(){
	lock.readLock.lock();
	try{
		
	}finally{
		lock.readLock.unlock();
	}
}
public void write(){
	lock.writeLock.lock();
	try{
		
	}finally{
		lock.writeLock.unlock();
	}
}

            与ReentrantLock相比效率更高.
        通常在finally中释放锁,可以有效避免死锁.
        与synchronized相比操作性更好.

    3.Atomic类(原子操作类):
        通过volatile和CAS在硬件层面实现线程安全和同步,Atomic类是乐观锁(乐观锁其实是不加锁的).
        分类:
            基本类:
                AtomicInteger:
                    常用方法:
                    set(int newValue)
                    get()
                    getAndSet(int newValue):设置为新值,返回旧值.
                    compareAndSet(int expect, int update):如果当前值为expect,则设置新值为update,返回是否成功.
                    addAndGet(int delta):当前值+delta,返回新值.
                    incrementAndGet():当前值+1,返回新值.
                    decrementAndGet():当前值-1,返回新值.
                    getAndAdd(int delta):当前值+delta,返回旧值.
                    getAndIncrement():当前值+1,返回旧值.
                    getAndDecrement():当前值-1,返回旧值.
                AtomicLong:
                    常用方法同AtomicInteger.
                AtomicBoolean:
                    常用方法:
                    set(boolean newValue)
                    get()
                    getAndSet(boolean newValue)
                    compareAndSet(boolean expect, boolean update)
            引用类:
                AtomicReference<V>:
                    常用方法,方法解释参考AtomicInteger:
                    set(V newValue)
                    get()
                    getAndSet(V newValue)
                    compareAndSet(V expect, V update)
                AtomicMarkableReference:带标记位的原子引用类.
                AtomicStampedReference:带版本号的原子引用类.
            数组类:
                AtomicIntegerArray:
                    常用方法:
                    length():返回数组长度.
                    set(int i, int newValue):将数组下标为i的元素设置为newValue.
                    get(int i):返回数组下标为i的元素.
                    getAndSet(int i, int newValue):将数组下标为i的元素设置为新值,返回旧值.
                    compareAndSet(int i, int expect, int update):如果数组下标为i的元素当前值为expect,则设置新值为update,返回是否成功.
                    addAndGet(int i, int delta):将数组下标为i的元素当前值+delta,返回新值.
                    incrementAndGet(int i):将数组下标为i的元素当前值+1,返回新值.
                    decrementAndGet(int i):将数组下标为i的元素当前值-1,返回新值.
                    getAndAdd(int i, int delta):将数组下标为i的元素当前值+delta,返回旧值.
                    getAndIncrement(int i):将数组下标为i的元素当前值+1,返回旧值.
                    getAndDecrement(int i):将数组下标为i的元素当前值-1,返回旧值.
                AtomicLongArray:
                    同AtomicIntegerArray.
                AtomicReferenceArray<E>:
                    常用方法:
                    length()
                    set(int i, E newValue)
                    get(int i)
                    getAndSet(int i, E newValue)
                    compareAndSet(int i, E expect, E update)
            更新器类:
                更新器类对应的字段必须使用"public volatile"修饰.
                AtomicIntegerFieldUpdater<T>:
                    常用方法:
                        newUpdater(Class<U> tclass, String fieldName):为具有给定字段的对象创建并返回更新器,对象类型为tclass,字段名为fieldName.
                        set(T obj, int newValue):将obj对象对应字段设置为newValue.
                        get(T obj):返回obj对象对应字段.
                        getAndSet(T obj, int newValue):将obj对象对应字段设置为新值,返回旧值.
                        compareAndSet(T obj, int expect, int update):如果obj对象对应字段当前值为expect,则设置新值为update,返回是否成功.
                        addAndGet(T obj, int delta):将obj对象对应字段当前值+delta,返回新值.
                        incrementAndGet(T obj):将obj对象对应字段当前值+1,返回新值.
                        decrementAndGet(T obj):将obj对象对应字段当前值-1,返回新值.
                        getAndAdd(T obj, int delta):将obj对象对应字段当前值+delta,返回旧值.
                        getAndIncrement(T obj):将obj对象对应字段当前值+1,返回旧值.
                        getAndDecrement(T obj):将obj对象对应字段当前值-1,返回旧值.
                    使用方式:

public TestAtomicIntegerFieldUpdater{
	public static AtomicIntegerFieldUpdater<User> aifu=AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
	public static void main(String[] args) {
		User user=new User(20);
		aifu.set(user,21);
		aifu.incrementAndGet(user);
		aifu.addAndGet(user,2);
		aifu.compareAndSet(user,24,27);
		System.out.println(aifu.get(user));
	}
	static class User{
		public volatile int age;
		public User(int age){
			this.age=age;
		}
	}
}
输出:
	27

                AtomicLongFieldUpdater<T>:
                    同AtomicIntegerFieldUpdater.
                AtomicReferenceFieldUpdater<T,V>:
                    常用方法:
                    newUpdater(Class<U> tclass, Class<W> vclass, String fieldName):为具有给定字段的对象创建并返回更新器,对象类型为tclass,字段类型为vclass,字段名为fieldName.
                    set(T obj, V newValue)
                    get(T obj)
                    getAndSet(T obj, V newValue)
                    compareAndSet(T obj, V expect, V update)
                    使用方式:

public TestAtomicReferenceFieldUpdater{
	public static AtomicReferenceFieldUpdater<User,String> arfu=AtomicReferenceFieldUpdater.newUpdater(User.class,String.class,"name");
	public static void main(String[] args) {
		User user=new User("tom");
		arfu.set(user,"jack");
		arfu.compareAndSet(user,"jack","sam");
		System.out.println(arfu.get(user));
	}
	static class User{
		public volatile String name;
		public User(String name){
			this.name=name;
		}
	}
}
输出:
	sam

    4.BlockingQueue<E>(阻塞队列):
        BlockingQueue为接口,通过ReentrantLock和Condition来保证同步,主要用于生产者消费者模式.
        实现类:
            ArrayBlockingQueue<E>:使用方式类似于ArrayList.
            LinkedBlockingQueue<E>:使用方式类似于LinkedList.
        公有方法:
            插入方法:
                add(E e) : 添加成功返回true,失败抛IllegalStateException异常.
                offer(E e) : 成功返回 true,如果此队列已满,则返回 false.
                put(E e) :将元素插入此队列的尾部,如果该队列已满,则一直阻塞.
            删除方法:
                remove(Object o) :移除指定元素,成功返回true,失败返回false.
                poll() : 获取并移除此队列的头元素,若队列为空,则返回 null.
                take():获取并移除此队列头元素,若没有元素则一直阻塞.
            检查方法:
                element() :获取但不移除此队列的头元素,没有元素则抛异常.
                peek() :获取但不移除此队列的头;若队列为空,则返回 null.

    5.volatile关键字:
        volatile是变量修饰符,其修饰的变量具有可见性,但不能保证操作的原子性,所以不能保证并发的正确性.
        可见性:是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的.

    6.ThreadLocal<T>(线程局部变量):
        ThreadLocal为使用该变量的线程提供一个独立的副本,在各个线程互不影响,因此保证了线程安全,但并不保证同步.
        常用方法:
            initialValue():设置当前线程该变量副本初始值,重写时使用.
            get():获取当前线程该变量副本.
            set(T value):设置当前线程该变量副本.
            remove():删除当前线程该变量副本,用于该变量不再使用后,避免内存泄漏.
        使用方式:

public class TestThreadLocl{
	public static ThreadLocal<Integer> value=new ThreadLocal<Integer>(){
		@Override
		protected Integer initialValue() {
			return 0;
		}
	};
	public static void main(String[] args) throws InterruptedException {
		System.out.println("main:"+value.get());
		value.set(1);
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("thread:"+value.get());
				value.set(2);
				System.out.println("thread:"+value.get());
			}
		}).start();
		Thread.sleep(1000);
		System.out.println("main:"+value.get());
	}
}
输出:
	main:0
	thread:0
	thread:2
	main:1		

参考博客:

https://blog.csdn.net/evankaka/article/details/44153709#t1

https://blog.csdn.net/evankaka/article/details/44153709#t1

https://blog.csdn.net/sinat_36042530/article/details/52565296

https://blog.csdn.net/i_am_kop/article/details/80958856

https://www.cnblogs.com/chengxiao/p/6528109.html#t1

https://blog.csdn.net/woshiluoye9/article/details/72544764

https://blog.csdn.net/javazejian/article/details/77410889?locationNum=1&fps=1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值