java多线程2

来源:互联网 发布:淘宝话费充值店铺介绍 编辑:程序博客网 时间:2024/06/08 09:26

1.中断线程

  void interrupt()向线程发送中断请求,线程的中断状态将被置为true,如果目前线程被一个sleep调用阻塞,那么,InterruptedException异常被抛出。
   static boolean interrupted()测试当前线程是否被中断,静态方法,该方法调用会将当前线程的中断状态置为false
  boolean inIterrupted()测试线程是否被终止,不改变线程的中断状态;
  static Thread currentThread()返回代表当前执行线程的Thread对象;

2.线程状态

线程6种状态:
1.新创建New
2.可运行Runnable:调用start方法,可能正在运行也可能没有在运行;
3.被阻塞Blocked和等待Waiting:暂时不活动,不运行任何代码且消耗最少的资源;
 阻塞:一个线程试图获取一个内部的对象锁,而该锁被其他线程持有,则该线程进入阻塞状态,当所有其他线程释放该锁,并且线程调度器允许线程持有它的时候,该线程变成非阻塞;
 等待:当线程等待另一个线程通知调度器一个条件时,它自己进入等待状态,例如:调用Object.wait()或者Thread.join()或者等待java.util.concurrent库中的Lock或condition时,就会等待。
 计时等待:超时参数,状态一直保持到超时期满或者收到适当的通知,例如:Thread.sleep(),Object.wait(),Thread.join(),Lock.tryLock()以及Condition.await()的计时版;
4.被终止的线程Terminated:run方法正常退出或者异常;
  Thread类的一些方法:
  void join()
  等待指定的线程
  void join(long millis)
  等待指定的线程死亡或者经过指定的毫秒数
  Thread.State getState()
  得到线程的状态

3.线程属性

1.线程优先级

  Thread的一些方法:
  void setPriority(int priority):设置线程的优先级,0-10
  Static int MIN_PRIORITY MAX_PRIORITY NORM_PRIORITY
  Static void yeild():使当前执行线程处于让步状态;同等或者高优先级的其他进程将被调度;静态方法;

2.守护线程

  t.setDaemon(true);将线程转换为守护线程daemon thread;守护线程的唯一用途就是为其他线程提供服务;当只剩下守护进程时,虚拟机就退出了,不建议访问固有资源,因为该进程随时可以发生中断;这个方法必须在线程启动之前调用;

3.未捕获异常处理器

  线程死亡之前,异常被传递给一个用户未捕获异常的处理器。该处理器必须属于实现Thread.UncaughtExceptionHandler接口的类,这个接口只有一个方法,void uncaughtException(Thread t,Throwable e);可以用setUncaughtExceptionHandler方法为所有线程安装一个默认的处理器;如果不为独立的线程安装处理器,则该线程的ThreadGroup作为处理器。
  ThreadGroup类实现了上述接口,他的uncaughtException方法做如下操作:1.如果该线程有父线程组,那么父线程组的uncaughtException方法被调用;2.否则,如果Thread.getUncaughtExceptionHandler返回一个非空的处理器,则调用该处理器;3.否则,如果Throwable是ThreadDeath的一个实例,什么都不做;4.否则,线程的名字以及Throwable的栈踪迹被输出到System.err上。

4.同步

竞争条件 原子操作
防止代码块受并发访问的干扰:1.锁对象和条件对象;2.synchronized关键字
  1.锁对象:保证任何时刻只有一个线程进入临界区。其他线程调用lock()时将被阻塞,直到第一个线程释放锁对象;java.util.concurent.locks.Lock unlock ReentrantLock

public Lock bankLock = new ReentrantLock();//ReentrantLock构建一个可以被用来保护临界区的可重入锁public void transfer(int from,int to,int amount){    bankLock.lock();    try{临界区代码}    finally{myLock.unlock();}//解锁,如果临界区的代码抛出异常,锁必须释放,否则,其他线程将永远阻塞}

  2.条件对象: 线程进入临界区,需要满足一定的条件之后才能运行;一个锁对象可以有一个或多个相关的条件对象,可以使用newCondition方法获得一个条件对象,如果发现条件不满足,则会调用await方法阻塞,并放弃锁,当另一个线程调用signalAll或者signal方法时,才有机会被重新唤醒。没有办法唤醒自己。

public Lock bankLock = new ReentrantLock();//ReentrantLock构建一个可以被用来保护临界区的可重入锁public void transfer(int from,int to,int amount){    bankLock.lock();    try{        while(accounts[from]<amount)            sufficientFunds.await();        临界区代码        sufficientFunds.signalAll();    }    finally{myLock.unlock();}//解锁,如果临界区的代码抛出异常,锁必须释放,否则,其他线程将永远阻塞}

  3.synchronized关键字:java中的每个对象都有一个内部锁,如果一个方法用synchronized声明,那么对象的锁将保护整个方法,如果要调用该方法,线程必须获得内部的对象锁,并且满足其内部条件。
注意:wait,notifyAll以及notify方法是Object类的final方法,Condition方法必须被命名为await,signalAll和signal方法,以免发生冲突。
将静态方法声明为synchronized也是合法的,如果调用这个方法,获得相关的类对象的内部锁

class Bank{    private dounle[] accounts;    public synchronized void method() throws InterruptedException    {        while(accounts[from]<amount)            wait();        ...        notifyAll();    }   }

内部锁和条件存在一些局限,包括:
不能中断一个正在试图获得锁的线程;
试图获得锁时不能设定超时;
每个锁仅有一个单一的条件;
4.同步阻塞
使用一个对象的锁来实现额外的原子操作,称为客户端锁定;
就是将方法上的synchronized关键字往下移,同步代码块;

public void method(){    synchronized(accounts)    {        临界区操作    }}

5.监视器概念
监视器是只包含私有域的类;每个监视器类的对象有一个相关的锁,使用该锁对所有的方法进行加锁;该锁可以有任意多个相关条件。
6.Volatile域
volatile关键字为实例域的同步访问提供了一个免锁机制,如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能别另一个线程并发更新的。

private volatile boolean done;public boolean isDone{return done;}public void setDone(){done = true;}

7.final变量

final Map<String,Double> accounts = new HashMap<>();

将account设置为final,可以保证其他线程在构造函数完成构造之后才看到这个accounts变量,否知可能只看到null.
8.原子性
java.util.concurrent.atomic包中有很多类使用了很高效的机器级指令(而不是使用锁)来保证其他操作的原子性,例如AtomicInteger类提供了方法incrementAndGet和decrementAndGet,他们分别以原子方式将一个整数自增或自减,可以安全使用AtomicInteger作为共享计数器而无需同步;
还有AtomicBoolean,AtomicLong,AtomicReference原子数组;
9.死锁
锁和条件不能解决多线程中的所有问题,例如死锁,线程互相等待资源而被阻塞,或者signal方法唤醒的是一个不能执行的线程也会造成死锁。
10.线性局部变量
避免共享变量,使用ThreadLocal辅助类为各个线程提供各自的实例;例如SimpleDateFormat和Random;
11.锁测试与超时
tryLock方法试图申请一个锁,在成功获得锁后返回true,窦泽,立即范湖false,并且线程可以立即离开去做其他事情;
12.读写锁
java.util.concurrent.locks包定义了两个锁类,ReentrantLock类和ReentrantReadWriteLock;后者允许读者线程共享访问,对写线程互斥访问。

private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();private Lock readLock = rwl.readLock();private Lock writeLock = rwl.writeLock();//对所有获取方法加读锁public double getTotalBalance(){    readLock.lock();    try{}    finally(readLock.unclock();)}//对所有的修改方法加写锁public void transfer(){    writeLock.lock();    try{}    finally{writeLock.unlock();}}

5.阻塞队列

6.线程安全的集合

0 0
原创粉丝点击