zoukankan      html  css  js  c++  java
  • Java—进程与线程

    • 进程与线程

      进程是程序(任务)的执行过程,具有动态性;持有资源(共享内存、共享文件)和线程,是资源和线程的载体。

      线程是系统中最小的执行单元,同一进程中有多个线程,线程共享进程的资源。

      线程的交互,交互的方式包括互斥与同步。

    •  线程的常用方法

      java对线程的支持主要体现在类Thread和接口Runnable,它们都继承java.lang包,有一个共同的方法run()

       

    • 线程停止错误的方法:stop()、interrupt()
    • 线程停止的正确方法
    public class ArmyRunnable implements Runnable {
        //volatile保证了线程可以正确读取其他线程写入的值
        volatile boolean keepRunning = true;
        @Override
        public void run() {
            while(keepRunning) {
                //发动五连击
                for (int i = 0; i < 5 ; i++) {
                    System.out.println(Thread.currentThread().getName() + "进攻对方[" + i + "]");
                }
                //暂停
                Thread.yield();
            }
            System.out.println(Thread.currentThread().getName() + "结束了战斗");
        }
    }
    •  争用条件

      当多个线程同时共享访问同一数据(内存区域)时,每个线程都尝试操作该数据,从而导致数据被破坏(corrupted),这种现象称为争用条件。

    • 线程的交互:互斥与同步

      互斥:在同一时间,只能有一条线程去对我们的关键数据或临界区进行操作。

      互斥的实现:sysnchronized(intrinsic lock),sysnchronized相当于给代码加上一把锁,使其他线程不能进入这个关键区域访问我们的关键资源。

      同步:是线程之间的一种通信机制, 由于一条线程的某些条件不具备,使得其他线程处于某种等待的状态,之后由于条件具备了,一条线程会用某种方式唤醒其他的线程。

      同步的实现:wait()/notify()/notifyAll()--Object对象的成员方法

      wait set 是线程的休息室

    public void transfer(int from, int to, double amount) {
            //通过synchronized 关键字来实现互斥,synchronized既可以出现在方法之上,也能以块的形式出现在方法体之中
            //通过对lockObj加锁实现互斥
            //加锁操作是有开销的,多次加锁操作会降低系统的性能
            synchronized (lockObj) {//while循环,保证条件不满足时任务都会被条件阻挡,而不是继续竞争CPU资源
                while (energyBoxes[from] < amount) {
                    try {
                        //条件不满足,将当前线程放入锁对象(lockObj)上的wait set
                        //wait set 是线程的休息室
                        lockObj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName());
                energyBoxes[from] -= amount;
                System.out.printf("从%d转移%10.2f单位能量到%d", from, amount, to);
                energyBoxes[to] += amount;
                System.out.printf("能量总和:%10.2f%n",getTotalEnergies());
                
                //唤醒所有在lockObj对象上等待的线程
                lockObj.notifyAll();
            }
            
        }
    • Runnable方式和Thread方式创建线程的区别

     

    1. Runnable方式可以避免Thread方式由于Java单继承特性带来的缺陷
    2. Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况
    • 线程的生命周期

      

    1. 就绪:创建了线程对象后,调用了线程的start()方法(此时线程只是进入了线程队列,等待获取CPU服务,具备了运行的条件,但并不一定已经开始运行了)。
    2. 运行:处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑。
    3. 终止:线程的run()方法执行完毕,或者线程调用了stop()方法(这种方法已经out),线程便进入终止状态。
    4. 阻塞:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep()方法
    • 用户线程和守护线程
    1. 用户线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程
    2. 守护线程:运行在后台,为其他前台线程服务,一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作。
    3. 守护线程的应用:数据库连接池中的监测线程、JVM虚拟机启动后的监测线程。最常见的守护线程是垃圾回收线程
    4. 设置守护线程:通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程。注意:setDaemon(true)必须在start()方法之前调用,否则会抛出异常;在守护线程中产生的新线程也是守护线程;不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑。
    • 扩展

      Java Memory Mode

      Locks & Condition

      线程安全性: 原子性与可见性 ...

      多线程编程常用的交互模型

      Java5中并发编程工具

    • 参考书

      core java

      Java concurrency in practice

  • 相关阅读:
    编程题#2: 魔兽世界之二:装备
    程序设计实习MOOC / 继承和派生——编程作业 第五周程序填空题1
    【转】C++动态创建二维数组,二维数组指针
    HDU-2571命运
    HDU-1203 I NEED A OFFER!
    HDU-1003 Max Sum
    HDU2196-Computer
    HDU-1520 Anniversary party
    ChineseHelper(获取汉字字符串的首拼)
    车牌号正则表达式(新能源车牌)
  • 原文地址:https://www.cnblogs.com/tianxintian22/p/6858724.html
Copyright © 2011-2022 走看看