<<java编程思想>>笔记:并发1

回顾

  1. 图解:
    未命名文件.png

其中:

  • start()并不代表运行,只是表示我准备好了
  • 运行状态可进入由用户或代码而进入阻塞/等待状态,死锁时进入锁池状态
  • yield()暗示该线程已经做完了工作,可以让资源给其他角色(不保证立马结束)
  • 等待队列需要释放语句才能进入锁竞争队列,从而重新进入可运行状态
  • run结束或run背后的主线程结束时,over
  1. 常用实现
  • 实现Runnable接口(推荐)
public class Test implements Runnable {

    public void run() {
        // 只需要实现run方法即可

    }

    class test extends Thread {
        // 重写从thread继承的 run方法
        public void run() {

        }
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.run();
        test t2 = t.new test();//使用.new从外部类访问内部类
        t2.start(); //继承Thread的话 需调用start()方法先进入就绪状态
    }
  1. 使用Executors线程池
public class CachedThreadPool {
    public static void main(String[] args) {
        // 创建一个缓冲线程池服务,输入参数则创建固定线程个数的线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            // 线程池服务启动线程
            final int j = i;
            exec.execute(new Runnable() {
                // 匿名内部类实现线程
                public void run() {
                    System.out.println("Thread " + j + " is running");
                }
            });
            // 线程池服务停止
        }
        exec.shutdown();
    }
}
  • 使用Executors.newSingleThreadPool()可创建单线程池,一般用于长时间存活的单任务,例如网络socket连接
  1. 获取线程返回值,实现Runnable接口的线程没有返回值, 需要额外实现Callable接口.
public class CachedThreadPool {
    //创建一个继承自Callable的线程,使其能够返回线程值,
    //call方法相当于带有返回值的run方法
    class TakWithResult implements Callable<String> {
        private int id;
        public  TakWithResult(int id) {
            // TODO Auto-generated constructor stub
            this.id = id;
        }
        @Override
        public String call() throws Exception {
            // TODO Auto-generated method stub
            return "result of TaskWhithr " + id;
        }
    }
    public static void main(String[] args) {
        // 创建一个缓冲线程池服务,输入参数则创建固定线程个数的线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        List<Future<String>> results = new  ArrayList<Future<String>>();
        CachedThreadPool ca = new CachedThreadPool();
        for (int i = 0; i < 5; i++) {
            results.add(exec.submit(ca.new TakWithResult(i)));
            // 线程池服务启动线程
            final int j = i;
            exec.execute(new Runnable() {
                // 匿名内部类实现线程
                public void run() {
                    System.out.println("Thread " + j + " is running");
                }           
            });
            // 线程池服务停止
        }
        //通过call方法在线程外部获取线程返回值
        for(Future<String> fs : results) {
            try {
                System.out.println(fs.get());
            }catch (Exception e) {
                System.out.println(e);// TODO: handle exception
            }finally {
                exec.shutdown();
            }
        }
    }
}

5.线程休眠Thread.sleep(1000)

  • 线程休眠的方法是TimeUnit枚举类型中的方法,等同于jdk5之后的新方法,效果都为休眠一秒
    TimeUnit.SECONDS.sleep(1);
  • 线程休眠方法都要捕获InterruptedExecutors异常
  1. 线程优先级
  • 指线程被线程调度器调度执行的优先级顺序,优先级越高,表示获取cpu允许时间的概率就越大,但是不是绝对,因为线程调度器调度不可控,最高10,最低1
  • 通过方法yield()/setPriority()来给县城调度器提供建议
  1. 守护线程
  • 是某些提供通用服务的在后台运行的程序,是优先级最低的线程,当所有非守护线程结束后,程序会结束所有的守护线程而终止程序运行,如果当前还有非守护线程正在于心,则不会进行终止操作
public class SimpleDaemons implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            System.out.println("start daemons ");
            TimeUnit.SECONDS.sleep(1);
        }catch (Exception e) {
            // TODO: handle exception
            System.out.println("sleep() interrupted");
        }finally {
            System.out.println("finally go ");
        }
    }

    public static void main(String[] args) {
        Thread daemon = new Thread(new SimpleDaemons());
        //去除注释即可设置守护线程
        //daemon.setDaemon(true);
        daemon.start();
    }
}
  • 设置该线程为守护线程后,main()则成为唯一的非守护线程,当线程在休眠时,main执行结束,jvm检测到只有守护线程在运行,则终止程序,无法执行finally的内容
  • 使用setDaemon方法设置守护线程,通过isDaemon方法判断一个线程是否为守护线程
  • 由守护线程创建的线程对象不论有没有通过setDaemon方法显示设置,都是守护线程(也说明了能设置多个守护线程)
  1. synchronized 线程同步
  • 用于对共享资源加锁,防止同时访问

a. 方法同步

public synchronized void methodA(){
  syso(this);
}

-对方法加锁后,通对象的不同线程,在同一时刻,只能有一个线程能够调用methodA方法

b. 静态方法(类对象)同步

public synchronized static void methodA(){
  syso(this);
}
  • 静态方法的线程同步锁对类的所有对象都起作用,即所有对象的线程在同一时刻,只有一个类的一个线程能够调用该方法

c. 对象同步代码块

public void methodC(){
synchronized(this){
syso(this);
}
}
  • 使用当前对象作为线程的同步锁,同一个对象的不同线程,在同一时刻只能有一个线程调用methodc方法, 好像和a一样

d. 类同步代码块

public void methodD(){
  synchronized(className.class){
  syso(this);
}
}
  • 使用类字节码对象作为线程同步锁,类所有对象的所有线程,在同一时间内,只能有一个类的一个线程调用methodD的同步代码块
注意: 线程的同步针对对象, 不论同步方法还是同步代码块,都是锁定的对象,而非代码块和方法本身,每一个对象只能有一个线程同步锁与之关联
  • 如果一个对象有多个线程同步方法, 只要有一个线程访问了其中一个线程同步方法,其他线程就不能同时访问这个对象中任何一个线程同步方法

  • 同步代码块和同步方法的区别在于前者可以使多个任务访问对象的时间性能得到显著提升

  1. 线程锁
  • 在java.util.concurrent.locks包中引入了线程锁机制,编程中可以显式锁定确保线程间
  • ReentrantLock可以通过lock()锁定对象,也可通过tryLock()方法来锁定对象,对于显式使用线程锁的方法体或代码块必须放在try-catch-finally块中,必须在finally中释放对象锁.
  • 与Synchronized相似,但是后者更复杂,能手动控制锁定状态与实践,功能更全面
  1. volatile关键字
  • 确保变量跨程序可见性,告诉编译器移除线程中的读写缓存,直接从内存中读写,使用volatile声明的域,只要发生了写改动,会立即写入内存,所有读取该字段的值都会跟着改变,即使使用了本地缓存任然会改变
  • 不使用状况
    a. 一个域完全由synchronized方法或语句块防护,就不必使用volatile.
    b. 当一个域的值依赖于它之前的值时(递增,设计一个读与一个写,不是原子性)
    c. 如果某个域的值受到其他域的限制(range类的lower和upper边界必须遵循lower <= upper的限制)
  • 第一选择是使用synchronized方式,最简洁最安全

代码目测记事本手撸,小错误很多,都修正了下
原帖传送门

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容