当前位置:网站首页 > Java教程 > 正文

java线程教程例子



  • 让子类继承Thread线程类
  • 子类必须重写Thread类的run方法
  • 创建一个自己定义的线程对象
  • 调用start()方法启动线程
 
 
 
  • 创建一个任务类实现Runnable方法
  • 实现Runnable接口的run方法
  • 创建一个任务类对象
  • 把任务对象交给Thread线程类处理
  • 调用线程对象start方法启动线程
 
 
 

扩展

由于每次创建线程都要创建一个实现接口的类,非常麻烦,可以用匿名内部类或Lambda表达式代替

 
 
 

​ 前面几种方法创建的线程均没有返回值,假如线程执行完毕后需要返回,可以用这种方式。

  • 定义一个实现Callable接口的类,指定返回数据的类型
  • 重写call方法,指定返回类型
  • 创建一个Callable对象,注意该对象不是还不是任务对象
  • Callable类型的对象封装成FutureTask类型的对象
  • 把任务对象交给Thread对象
  • 获取线程执行完毕后返回的结果
 
 
 
Thread提供的常用方法 说明 public void run() 线程的任务方法 public void start() 启动线程 public String getName() 获取当前线程的名称,线程名称默认是Thread-索引 public void setName(String name) 为线程设置名称 public static Thread currentThread() 获取当前执行的线程对象 public static void sleep(long time) 让当前执行的线程休眠多少毫秒后再执行 public final void join() 让调用当前这个方法的线程先执行玩
Thread提供的常见构造器 说明 public Thread(String name) 可以为当前线程指定名称 public Thread(Runnable target) 封装Runnable对象为线程对象 public Thread(Runnable target, String name) 封装Runnable对象为线程对象,并指定线程名称

什么是线程安全问题?

答:多线程同时操作同一临界资源,导致结果存在的不准确性。

例题:当两个人同时对同一账号取钱,其其结果导致第一个人把前全部取走,二第二个人还可以继续取钱。

 
 
 
 

什么是线程同步

答:线程同步是指一个或多个线程必须等待某个或多个线程执行完某些操作后才能继续往下执行,常用于多线程同时操作同一临界资源问题,但某线程在操作某一临界资源时,其他线程必须等待。

实现线程同步有三种方法:同步代码块、同步方法、lock锁

作用:把访问共享资源的核心代码给上锁,但此线程执行完后会自动解锁,以此保证线程安全。

 

对之前取钱操作加同步锁

 
 

注意:这个锁其实是一个对象,这个对象被引用的时候会被标记,解锁后才会消除标记

所以就有一个问题,如果有小红、小蓝、小黑、小白,四个线程,而业务只需要小红小蓝同步,小黑小白同步,如果锁对象是唯一的,则所有的线程都用同一把锁,则红蓝黑白都会被同步,明明两组不相干的操作却要一起同步等待,就会影响效率,所以要想把两组同步分开,就要加不同的锁,用 this

 
 
 

用this可以识别调用不同对象的线程,但如果要在静态方法里上锁,因为静态方法是直接用类名调用的,不需要创建对象,这时可以用这个类的唯一标识当锁,而这个类的唯一标识是字节码(类名.class)

 

锁对象的使用规范

  • 建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。
  • 对于静态方法建议使用字节码(类名.class)对象作为锁对象。

作用:把访问共享资源的核心方法给上锁,以此保证线程安全。

 

同步方法底层原理

  • 同步方法其实底层也是隐式锁对象的,只是锁的范围是整个方法代码。
  • 如果方法是实例方法:同步方法默认用this作为的锁对象。
  • 如果方法是静态方法:同步方法默认用类名.class作为锁对象。
 
  • Lock锁是JDK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便。
  • Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象。
  • Lock常用方法
    变量类型 方法名称 说明 void lock() 获得锁。 void lockInterruptibly () 除非当前线程是interrupted,否则获取锁定。 Condition newCondition() 返回一个新Condition绑定到该实例Lock实例。 boolean tryLock () 只有在调用时他是空闲的才能获取锁。 boolean tryLock (long time,TimeUnit unit) 如果锁在给定的等待时间内是空闲的并且当前线程不是interrupted,则获取锁。 void unlock () 释放锁定。

什么是线程池
答:线程池就是一个可以复用线程的技术。
不使用线程池的问题
用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

谁代表线程池

答:JDK5.0起提供了代表线程池的接口:ExecutorService。

如何得到线程池对象

  • 方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象,
  • 方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。
 
  • 对于计算机密集型的任务(使用CPU频繁),主机逻辑处理器核数 + 1
  • 对于IO密集型的任务,主机逻辑处理器核数 * 2
 

1、临时线程什么时候创建?
答:新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
2、什么时候会开始拒绝新任务
答:核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

方法名称 说明 void execute(Runnable comand) 执行 Runnable 任务 Future submit(Callable task) 执行 Callable 任务,返回未来任务对象,用于获取线程返回的结果 void shutdown() 等全部任务执行完毕后,再关闭线程池 List shutdownNow 立即关闭线程池,停止正在执行的任务,并返回队列中未执行任务
 
 
 
 
 
  • 当任务队列未满时不创建临时线程
 
 
  • 当核心线程在忙且任务队列已满时创建创建临时线程
 
 
  • 当核心线程和临时线程在满,且任务列表满时,再有任务请求则调用拒绝策略
  • 常用策略
策略 详解 ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException.异常。是默认的策略 ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常这是不推荐的做法 ThreadPoolExecutor.DiscardoldestPolicy 抛弃队列中等待最久的任务然后把当前任务加入队列中 ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的ru0方法从而绕过线程池直接执行
 
 
 
 
 
  • Executors 工具底层都是通过线程池的实现类ThreadPoolExecutor创建的线程池对象。
  • 不建议使用这个Executors工具类实现线程池,因为在大型并发系统环境中使用Executors如果不注意可能会出现系统风险。用原始的创建方法可以让开发者更好的理解线程池执行流程,也可以控制线程池一些数据来规避风险。
  • 常用方法
方法名称 说明 public static ExecutorService newFixedThreadPool(int nThreads) 创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。 public static ExecutorService newsingleThreadExecutor() 创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。 public static ExecutorService newCachedThreadPool() 线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了6s则会被回收掉。 public static ScheduledExecutorService newScheduledThreadPool(int corePoolsize) 创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。

Java总共定义了6种状态。

6种状态都定义在Thread类的内部枚举类中

 
线程状态 说明 NEW(新建) 线程刚被创建,但是并未启动。 Runnable(可运行) 线程已经调用了start(),等待CPU调度。 B1 ocked(锁阻塞) 线程在执行的时候未竞争到锁对象,则该线程进入Blocked状态。 Waiting(无限等待) 一个线程进入Waiting状态,另一个线程调用notify或者notifyAll方法才能够唤醒 Timed Waiting(计时等待) 同waiting状态,有几个方法(sleep,wait)有超时参数,调用他们将进入Timed Waiting状态。 Teminated(被终止) 因为ru方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

注意得到锁的线程调用 sleep() 进入等待状态,期间不会释放锁,而 wait() 会释放锁。

  • 上一篇: java图片使用教程
  • 下一篇: java纯小白教程
  • 版权声明


    相关文章:

  • java图片使用教程2025-03-22 21:10:01
  • 国外java教程2025-03-22 21:10:01
  • java布尔类型教程2025-03-22 21:10:01
  • java api教程2025-03-22 21:10:01
  • java 大学教程 中文版2025-03-22 21:10:01
  • java纯小白教程2025-03-22 21:10:01
  • java安装激活教程2025-03-22 21:10:01
  • java压缩流教程2025-03-22 21:10:01
  • Java破解游戏教程2025-03-22 21:10:01
  • java菜鸟教程在线2025-03-22 21:10:01