知识大全 Java多线程提升

Posted

篇首语:成功的人是跟别人学习经验,失败的人只跟自己学习经验。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java多线程提升相关的知识,希望对你有一定的参考价值。

Java多线程提升  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  一 多线程基本概念

  独占:通过阻止多个并发行为间的有害干扰来维护状态的一致性 通常使用异步方法sychronized

  状态依赖:触发 阻止 延迟 恢复 某些行为是由一些对象是否处在这些行为可能成功或者已经

  成功的状态决定的 主要通过监视器(monitor)实现 object wait object notify object notifyAll

  客户Client: Client Object 期待某个动作的执行

  服务Serverce :包括执行这个动作的代码

  主体 客户和服务都可以是一个对象 这个对象就是一个主体 而又他调用的对象通常就是辅助对象(help)

  Synchronized: 防止并法导致数据不一致 可以修饰一个方法或者代码块

   Object 或子类的每一个实例都会在进入这个synchronized方法前加锁 并在离开这个方法时自动释放锁

  使用synchronized关键字来定义方法就会锁定类中所有使用synchronzied关键字定义的静态方法或非静态方法

  不同的对象实例的synchronized方法是不相干扰的 也就是说 其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法

  对于修饰静态的方法它可以对类的所有对象实例起作用

   对代码块的加锁也是 只是需要指明对那个对象加锁 在静态代码块中使用类 class来指明

  在非静态代码块中多数是用this

   synchronized关键字是不能继承的 也就是说 基类的方法synchronized f() 在继承类中并不自动是synchronized f() 而是变成了f() 继承类需要你显式的指定它的某个方法为synchronized方法

  规则

   )永远只是在更新对象的成员变量是加锁

   )永远只是在访问有可能被更新对象的成员变量时加锁

   )永远不要在调用其它对象的方法时加锁

  二 ncurent 包介绍

   执行器(Executor) 用来管理Thread 对象 下面介绍三种Executor

  ( ) newCachedThreadPool

  ExecutorService exec = Executors newCachedThreadPool();//创建一个可根据需要创建新线程的线程池

  for(int  = ; i< ; i++)

  exec execute(new LiftOff());//LiftOff implements Runnable接口的类

  exec shutdown()

  

  ( ) newFixedThreadPool

  ExecutorService exec = Executors newFixedThreadPool( );//创建一个可重用固定线程数的线程池 以共享的无界队列方式来运行这些线程

  for(int  = ; i< ; i++)

  exec execute(new LiftOff());//LiftOff implements Runnable接口的类

  exec shutdown()

  

  ( ) newSingleThreadPool

  SingleThreadPool 就好象是线程数量为 的FixedThreadPool 如果向SingleThreadPool提交多个任务 那么这些任务都将排列 每个任务都会在下一个任务开始之前运行结束

  ExecutorService exec = Executors newSingleThreadPool();//创建一个使用单个 worker 线程的 Executor 以无界队列方式来运行该线程

  for(int  = ; i< ; i++)

  exec execute(new LiftOff());//LiftOff implements Runnable接口的类

  exec shutdown()

  

   从任务中产生返回值

  Runnable是执行工作的独立任务 但是不返回任何值 如果实现Callable 接口 则Callable接口方法call()可以返回一个值

  package cdl chen;

  /**

  * @ Class CallableDemo java

  * @ Description

  * @ Company OpenData

  * @ Author yinlei

  * @ Version

  * @ Date Mar

  */

  import java util ArrayList;

  import ncurrent Callable;

  import ncurrent ExecutorService;

  import ncurrent Executors;

  import ncurrent Future;

  public class CallableDemo

  public static void main(String[] args)

  ExecutorService exec = Executors newCachedThreadPool();

  ArrayList<Future<String>> results = new ArrayList<Future<String>>();

  for(int i = ; i < ; i++)

  results add(exec submit(new TaskWithResult(i)));//这里使用submit 方法会产生Future 对象

  

  for(Future<String> fs:results)

  try

  if(fs isDone())//检查Future是否已经完成 或者不用isDone()来检查 那么get()将会阻塞 直到结果准备就绪

  System out println(fs get());//通过get()得到call()方法返回的值

  

   catch(Exception ex)

  ex printStackTrace();

   finally

  exec shutdown();

  

  

  

  

  class TaskWithResult implements Callable<String>

  private int id;

  public TaskWithResult(int id)

  this id = id;

  

  public String call()

  return result of TaskWithResult + id;

  

  

  //结果

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  result of TaskWithResult

  sleep() 和wait()方法的区别

  sleep是Thread类的静态方法 sleep的作用是让线程休眠制定的时间 在时间到达时恢复 也就是说sleep将在接到时间到达事件事恢复线程执行 其控制范围是由当前线程块

  wait是Object的方法 也就是说可以对任意一个对象调用wait方法 调用wait方法将会将调用者的线程挂起 直到其他线程调用同一个对象的notify方法才会重新激活调用者

  sleep()是让某个线程暂停运行一段时间 其控制范围是由当前线程决定 也就是说 在线程里面决定 好比如说 我要做的事情是 点火 >烧水 >煮面 而当我点完火之后我不立即烧水 我要休息一段时间再烧 对于运行的主动权是由我的流程来控制

  而wait() 首先 这是由某个确定的对象来调用的 将这个对象理解成一个传话的人 当这个人在某个线程里面说 暂停! 也是 thisOBJ wait() 这里的暂停是阻塞 还是 点火 >烧水 >煮饭 thisOBJ就好比一个监督我的人站在我旁边 本来该线 程应该执行 后执行 再执行

  而在 处被那个对象喊暂停 那么我就会一直等在这里而不执行 但正个流程并没有结束 我一直想去煮饭 但还没被允许 直到那个对象在某个地方说 通知暂停的线程启动! 也就是thisOBJ notify()的时候 那么我就可以煮饭了 这个被暂停的线程就会从暂停处 继续执行

  本质的区别是一个线程的运行状态控制 一个是线程之间的通讯的问题

   t join();方法

  package cdl chen;

  /**

  * @ Class Joining java

  * @ Description

  * @ Company OpenData

  * @ Author yinlei

  * @ Version

  * @ Date Mar

  */

  class Sleeper extends Thread

  private int duration;

  public Sleeper(String name int sleepTime)

  super(name);

  duration = sleepTime;

  start();

  

  public void run()

  try

  sleep(duration);

  catch(InterruptedException ex)

  System out println(this getName()+ was interrupted + isInterrupted(): +this isInterrupted());

  

  System out println(this getName()+ has awakened );

  

  

  class Joiner extends Thread

  private Sleeper sleeper;

  public Joiner(String name Sleeper sleeper)

  super(name);

  this sleeper = sleeper;

  start();

  

  public void run()

  try

  sleeper join();//线程Sleeper在线程Joiner上执行join() 则Joiner 线程将被挂起 直到sleeper 线程结束(isAlive()==false) 才恢复

   catch(InterruptedException ex)

  System out print( Interrupted );

  

  System out println(this getName()+ join pleted );

  

  

  public class Joining

  public static void main(String []args)

  Sleeper sleepy = new Sleeper( Sleepy );

  Sleeper grumpy = new Sleeper( Grumpy );

  Joiner dopey = new Joiner( Dopey sleepy);

  Joiner doc = new Joiner( Doc grumpy);

  grumpy interrupt();//grumpy 中断 doc 将继续

  

  

  out put:

  Grumpy was interrupted isInterrupted():false//当线程在该线程上调用interrupt()时 将给该线程设定一个标志 然而 异常在捕获时会清理这个标志 所以在catch 代码块里调用interrupt()总是false

  Grumpy has awakened

  Doc join pleted

  Sleepy has awakened

  Dopey join pleted

   显示加锁 ncurrent locks

  public synchronized int next()

  

  try

  return

  catch()

  

  

  private Lock lock = new ReentrantLock();

  public  int next()

  try

  lock lock();

  

  return

   catch()

  lock unlock();

  

  使用synchronized关键字和显示Lock都可以解决资源同步的问题 并且synchronized 关键字比显示加锁代码量少更少 但是当synchronized关键字不

  能尝试获取锁一段时间 然后放弃它

   线程本地化 java lang ThreadLocal

  它的功用非常简单 就是为每一个使用该变量的线程都提供一个变量值的副本 是每一个线程都可以独立地改变自己的副本 而不会和其它线程的副本冲突 从线程的角度看 就好像每一个线程都完全拥有该变量

  通常通过get() set()方法来访问该对象的内容 get()方法返回与其线程相关联的对象副本 而set()方法将参数值插入到为其线程存储的对象里

  package cdl chen;

  import java util Random;

  import ncurrent ExecutorService;

  import ncurrent Executors;

  import ncurrent TimeUnit;

  class Accessor implements Runnable

  private final int id;

  public Accessor(int idn)id = idn;

  public void run()

  while(!Thread currentThread() isInterrupted())

  ThreadLocalVariableHolder increment();

  System out println(this);

  Thread yield();

  

  

  public String toString()

  return # +id+ : +ThreadLocalVariableHolder get();

  

  

  public class ThreadLocalVariableHolder

  private static ThreadLocal<Integer> value=

  new ThreadLocal<Integer>()

  private Random rand = new Random( );

  protected synchronized Integer initialValue()

  return rand nextInt( );

  

  ;

  public static void increment()

  value set(value get() + );

  

  public static int get()return value get();

  public static void main(String []args) throws Exception

  ExecutorService exec = Executors newCachedThreadPool();

  for(int i = ; i < ; i++)

  exec execute(new Accessor(i));

  

  TimeUnit SECONDS sleep( );

  exec shutdownNow();

  

  

  //output:

  # :

  # :

  # :

  # :

  # :

  # :

  # :

  # :

  # :

   线程中捕获异常

  任务的run()方法通常总会有某种形式的循环 使得任务一直运行下去直到不再需要 所以要设定跳出循环的条件

  通常 它被写成无限循环的形式这就意味着 除非有个条件使用它终止 否则它将永远运行下去

  由于线程的本质特性 所以我们不能捕获到从线程中逃逸的异常 比如:

  package chenlly;

  public class ThreadException implements Runnable

  public void run()

  throw new RuntimeException( I m throw Exception );

  

  public static void main(String []args)

  try

  Thread t = new Thread(new ThreadException());

  t start();

   catch(Exception ex)

  System out println( Exception has been handled! );

  ex printStackTrace();

  

  

  

  /* output

  Exception in thread Thread java lang RuntimeException: I m throw Exception

  at chenlly ThreadException run(ThreadException java: )

  at java lang Thread run(Unknown Source)

  也就是说tyr catch 无法捕获到从run 方法里逃逸的异常

  Thread UncaughtExceptionHandler这个接口就是当 Thread 因未捕获的异常而突然终止时 调用处理程序的接口

  它允许你在每个Thread对象上都附着一个异常处理器

  package chenlly;

  public class ThreadException implements Runnable

  public void run()

  throw new RuntimeException( I m throw Exception );

  

  public static void main(String[] args)

  Thread t = new Thread(new ThreadException());

  t setUncaughtExceptionHandler(new MyUncaughtException());//添加一个异常处理器

  t start();

  

  

  //异常处理器

  class MyUncaughtException implements Thread UncaughtExceptionHandler

  public void uncaughtException(Thread t Throwable e)

  System out println(t + : + e getMessage());

  

  

  /* output

  Thread[Thread main] : I m throw Exception

   线程之间的协助

  多个任务 可以通过使用锁或者synchronized(互斥)的方法来同步两个线程的行为 从而使的一个任务不会干涉另外一个任务的资源

  那么如何使得多个任务可以在一起彼此协作 去解决某个问题 使用相同的互斥基础 互斥 互斥能够确保只有一个任务可以响应某个信号

  eg:一个是将蜡涂到Car上 一个是抛光它 抛光任务在涂蜡完成之前是不能操作的 而涂蜡任务在涂另外一层蜡之前 必须等待抛光结束

  car 对象通过wait 和notifyAll来挂起和重新启动这些任务

  package chenlly;

  import ncurrent ExecutorService;

  import ncurrent Executors;

  import ncurrent TimeUnit;

  class Car

  private boolean waxOn = true;//默认为抛光状态 同步信号

  //打蜡完成 设置状态 并且唤醒打蜡

  public synchronized void waxed()

  waxOn = false;

  notifyAll();

  

  //抛光完成 设置状态 并且唤醒打蜡

  public synchronized void buffing()

  waxOn = true;

  notifyAll();

  

  //是否抛光结束

  public synchronized void waitForWaxed() throws InterruptedException

  while(!waxOn)

  wait();

  

  

  //是否打蜡结束

  public synchronized void waitForBuffing() throws InterruptedException

  while(waxOn)

  wait();

  

  

  

  //打蜡

  class WaxOn  implements Runnable

  private Car car;

  public WaxOn(Car car)

  this car = car;

  

  public void run()

  try

  while(!Thread interrupted())

  car waitForWaxed();

  System out println( Wax On! );

  TimeUnit SECONDS sleep( );

  car waxed();

  

   catch (Exception ex)

  ex printStackTrace();

  

  

  

  //抛光

  class Buffing  implements Runnable

  private Car car;

  public Buffing(Car car)

  this car = car;

  

  public void run()

  try

  while(!Thread interrupted())

  car waitForBuffing();

  System out println( Buffing On! );

  TimeUnit SECONDS sleep( );

  car buffing();

  

   catch (Exception ex)

  ex printStackTrace();

  

  

  

  public class WaxOMatic

  public static void main(String []args)

  try

  Car car = new Car();

  ExecutorService exec = Executors newCachedThreadPool();

  exec execute(new WaxOn(car));

  exec execute(new Buffing(car));

  TimeUnit SECONDS sleep( );

  exec shutdownNow();

   catch (InterruptedException ex)

  ex printStackTrace();

  

  

  

  /* output

  Wax On!

  Buffing On!

  Wax On!

  Buffing On!

  Wax On!

  Buffing On!

  打蜡和抛光相继进行 控制权在这两者之间相互传递时 这两个步骤过程在不断地重复 秒后中断这两个任务

   线程死锁问题

   死锁 某个任务在等待另外一个任务 而后者又在等待别的任务 这样一直下去 任务之间连续的循环就是死锁问题

  典型的哲学家就餐就是死锁问题

   死锁的四个必要条件

  ( ) 互斥条件:资源不能被共享 只能由一个进程使用

  ( ) 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源

  ( ) 非剥夺条件:经分配的资源不能从相应的进程中被强制地剥夺

  ( ) 循环等待条件(Circular wait):系统中若干进程组成环路 该环路中每个进程都在等待相邻进程正占用的资源

   处理死锁的策略

  通过破除死锁四个必要条件之一 来防止死锁产生

  哲学家就餐问题:该问题涉及到五个哲学家 他们交替地进行思考和进餐

  他们分别坐在位于一个圆形餐桌周围的五把椅子上 圆桌中央是一碗米饭 餐桌上共有五根筷子

  分别摆放在每两个相邻座位的中间

  当哲学家思考时 他不与其他人交谈 当哲学家饥饿时 他将拿起和他相邻的两根筷子进行进餐

  但他很可能仅拿到一根 此时旁边的另一根正在他邻居的手中

  只有他同时拿到两根筷子时他才能开始进餐 完成进餐后

cha138/Article/program/Java/gj/201311/27658

相关参考

知识大全 Java多线程编程基础之线程和多线程

Java多线程编程基础之线程和多线程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  随着计算机技

知识大全 Java多线程如何创建多个线程

Java多线程如何创建多个线程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java多线程的同

知识大全 超线程多核心下Java多线程编程分析

超线程多核心下Java多线程编程分析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一Java环

知识大全 超线程多核心下Java多线程编程技术分析[4]

超线程多核心下Java多线程编程技术分析[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb

知识大全 超线程多核心下Java多线程编程技术分析[3]

超线程多核心下Java多线程编程技术分析[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb

知识大全 超线程多核心下Java多线程编程技术分析[1]

超线程多核心下Java多线程编程技术分析[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb

知识大全 超线程多核心下Java多线程编程技术分析[2]

超线程多核心下Java多线程编程技术分析[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb

知识大全 Java多线程编程基础之线程对象

Java多线程编程基础之线程对象  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &nbs

知识大全 验证后台线程的java多线程技术

  这个程序验证了后台线程与用户线程的区别以及之间的关系证明了只要所有的用户线程结束了那么后台线程就将必须结束!  importncurrentTimeUnit;  publicclass 

知识大全 Java多线程处理机制

Java多线程处理机制  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一线程的同步  Java应