zoukankan      html  css  js  c++  java
  • Java多线程小结

    简述

    Java是支持多线程编程的语言,线程相比于进程更加轻量级,线程共享相同的内存空间,但是拥有独立的栈。减少了进程建立、销毁的资源消耗。jdk1.5后对java的多线程编程提供了更完善的支持,使得java的多线程编程更加方便简洁。本文旨在通过对Java多线程知识的梳理,整理出一个大纲,使得读者对多线程的编程有更加完善的认识。

    线程生命周期的管理

    • 线程的创建
      java中线程的创建主要有两种方式:
    1. 继承Thread类(Thread中方法主要用于针对线程本身的处理);
    2. 实现Runnable接口;
    • 线程的通讯
      线程之间的通讯实际上是线程之间传递参数的问题。
    1. 往线程中传递参数: 通过新建线程的构造函数;
    2. 线程执行中,往外界传递参数:
      • 通过方法的返回值,但可能线程未执行完成,所以返回NULL。所以,用轮询的方式,获取方法返回值。
        缺点是浪费CPU周期。
      • 通过注册回调方法,在构造线程的时候传入回调类,然后,在线程执行过程中调用回调方法。
      • JDK1.5,提供了Future、Callable和Executor,Executor子类ExecutorService创建线程,实现Callable接口作为回调方法(实现call()方法),返回一个Future类。
    • 线程同步
      当多线程共享资源时,必须考虑同步问题。可以用synchronized关键字标注关键对象或方法。但是,同步不仅影响性能,同步的越多越容易造成死锁问题。(死锁:两个线程想要独占某种资源,但是,两者同时占用这种资源的子集的情况)

      同步的替代方法:

    1. 尽可能使用局部变量而不是字段,基本类型传参是值传递,是线程安全的(String也是安全的,一旦创建不能更改);
    2. 构造函数一般不需要考虑线程安全问题;
    3. 将非线程安全的类作为线程安全类的一个私有字段;

    注:多线程中使用System.out输出,也属于共享资源。

    • 线程的调度
      JVM的线程调度器,抢占式的(preemptive)和协作式的(cooperative)。由于一个线程长时间占用CPU,会造成其他线程的饥饿状况。可以通过设置线程的优先级来改变这种情况,但是,在相同优先级的线程中,需要使用如下6种类方法,手动控制:
    1. 对I/O阻塞;
    2. 放弃,调用Thread.yield(),提供给相同优先级的线程CPU的使用机会;
    3. 休眠,sleep(),提供给相同优先级及以下优先级CPU的使用机会;
    4. 连接线程,join(),等待某个指定线程执行结束,或者执行一段时间;
    5. 等待某个对象,wait(),放弃对一个对象的锁定并暂停(之前的方法并不会放弃资源);
    6. 结束,方法返回return;

    线程池

    dk1.5对线程池提供了很好的支持。线程池的建立主要是为了减少内存资源的损耗,减少线程新建和删除的损耗,通过将任务(特定的线程)放置到队列中,然后,使用不同的策略,利用线程池中的线程处理队列中的任务。
    ExecutorService调用一个基础API创建线程池,通过不同队列实现不同特性的线程池。队列是独立于线程池的一部分,用于放置线程池中未及时处理的任务。

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 线程池包装
     */
    public class BearThreadPool {
    
        private ExecutorService pool;
    
        public void createCachedThreadPool(){
            pool = Executors.newCachedThreadPool();
        }
    
    
    
        public void addTask(Runnable task){
            pool.submit(task);
        }
    
        public void termination(){
            pool.shutdown();
        }
    }
    
    
    /**
     * 线程
     */
    public class Task implements Runnable {
    
        private String taskId;
        private TaskCallBack callback;
        public Task(String taskId, TaskCallBack callback){
            this.taskId = taskId;
            this.callback = callback;
        }
    
        public void run() {
            synchronized (System.out){
                System.out.println(taskId);
                callback.before();
                callback.middle();
                callback.after();
                System.out.println("==========");
            }
    
        }
    }
    
    
    /**
     * 回调函数接口
     */
    public interface TaskCallBack {
    
        void before();
    
        void middle();
    
        void after();
    
    }
    
    
  • 相关阅读:
    git(1)-git关联GitHub-windows-转载
    jenkins(4)-jenkins配置邮件通知
    jenkins(3)-linux下安装jenkins(yum install方式)
    【PAT甲级】1090 Highest Price in Supply Chain (25 分)(DFS)
    【PAT甲级】1087 All Roads Lead to Rome (30 分)(MAP【int,string】,邻接表,DFS,模拟,SPFA)
    【PAT甲级】1018 Public Bike Management (30 分)(DFS,SPFA)
    Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
    Atcoder Grand Contest 032C(欧拉回路,DFS判环)
    Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)
    Atcoder Grand Contest 031C(构造,思维,异或,DFS)
  • 原文地址:https://www.cnblogs.com/zhengruin/p/5939091.html
Copyright © 2011-2022 走看看