• java多线程


     一个线程是进程中的执行流程,一个进程可以同时包括多个线程,每个线程可以得到一段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。

    进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)

    线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)

    2、实现线程的两种方式

    2.1、继承Thread类

    Thread类是java.lang包中的一个类。

    通过该方法实现进程有三个步骤

    1)继承Thread类

    2)实现run()方法

    3)调用start()方法

    package com.pjf.thread;
    
    //继承Thread类
    public class ThreadTest extends Thread {
    
        private int count = 10;
    
        // 重写run()方法
        public void run() {
            while (true) {
                System.out.println(count + " ");
                if (--count == 0) {
                    return;
                }
            }
        }
    
        public static void main(String[] args) {
            ThreadTest threadTest = new ThreadTest();
            // 调用start()方法
            threadTest.start();
        }
    }

    2.2、实现runnable接口

    通过该方法实现进程有四个步骤

    1)实现Runnable接口

    2)重写run方法

    3)通过public Thread(Runnable r)构造方法来创建进程

    4)调用start()方法

    package com.pjf.runnable;
    
    //实现Runnable接口
    public class RunnableTest implements Runnable {
    
        private int count = 10;
    
        // 重写run方法
        public void run() {
            while (true) {
                System.out.println(count + " ");
                if (--count == 0)
                    return;
            }
        }
    
        public static void main(String[] args) {
            // 通过public Thread(Runnable r)构造方法来创建进程
            RunnableTest runnableTest = new RunnableTest();
            Thread thread = new Thread(runnableTest);
            // 调用start方法
            thread.start();
        }
    }

    3、线程的生命周期

    线程具有生命周期,包括七个状态,分别为初始状态、就绪状态、运行状态、锁池状态、等待状态、阻塞状态、死亡状态。

    初始状态:创建了一个进程对象。

    就绪状态:调用了该对象的start()方法。等待获取CPU的使用权就可以运行。

    运行状态:获取了CPU,执行程序代码

    锁池状态:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

    等待状态:调用对象的wait方法,进入等待状态,并释放进程锁。

    阻塞状态:调用对象的sleep或join方法,进入休眠状态,休眠结束后,转入就绪状态,等待获取cpu

    死亡状态:线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    4、函数说明

    sleep();

    yeild();

    join();

    synchronized;

    wait();

    notify();

    notifyAll();

    4.1、sleep() 在指定的毫秒数内让当前正在执行的线程休眠

    package com.pjf.runnable;
    
    public class RunnableTest implements Runnable {
    
        private int count = 10;
    
        public void run() {
            while (true) {
                System.out.println(count + " ");
                count--;
                try {
                    // 线程休眠
                    Thread.sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (count == 0)
                    return;
            }
        }
        public static void main(String[] args) {
            RunnableTest runnableTest = new RunnableTest();
            Thread thread = new Thread(runnableTest);
            thread.start();
        }
    }

    4.2、yeild()让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会

    package com.pjf.runnable;
    
    public class RunnableTestYeild implements Runnable {
    
        private int count = 10;
    
        public void run() {
            long beginTime = System.currentTimeMillis();
            int count = 0;
            for (int i = 0; i < 50000000; i++) {
                count = count + (i + 1);
                Thread.yield();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("用时:" + (endTime - beginTime) + " 毫秒!");
        }
    
        public static void main(String[] args) {
            RunnableTestYeild runnableTest = new RunnableTestYeild();
            Thread thread = new Thread(runnableTest);
            thread.start();
        }
    }

    4.3、join()主线程等待子线程的终止后才能继续执行

     泡茶前必须洗茶杯、烧开水,即使泡茶本身的动作的时间短于烧开水的时间,通过join()实现

    package com.pjf.join;
    
    public class Water extends Thread {
    
        public void run() {
        System.out.println("开始烧开水");
        try {        
            Thread.currentThread().sleep(1000);        
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束烧开水");
        }    
    }
    package com.pjf.join;
    
    public class WashTeaCup extends Thread {
        
        public void run() {
            System.out.println("开始洗茶杯");
            for(int i=0;i<5;i++){
                System.out.println("开始洗第"+i+"个茶杯");
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("结束洗第"+i+"个茶杯");
            }
        }
    }
    package com.pjf.join;
    
    public class MakeTea extends Thread {
        private WashTeaCup washTeaCup;
        private Water water;
    
        public MakeTea(WashTeaCup washTeaCup, Water water) {
            this.washTeaCup = washTeaCup;
            this.water = water;
        }
    
        public void run() {
            System.out.println("开始泡茶");
            try {
                washTeaCup.join();
                water.join();
                Thread.currentThread().sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("泡茶结束");
        }
    
        public static void main(String[] args) throws InterruptedException {
            WashTeaCup washTeaCup = new WashTeaCup();
            Water water = new Water();
            MakeTea makeTea = new MakeTea(washTeaCup, water);
            
            makeTea.start();
            water.start();
            washTeaCup.start();
        }
    }

    4.4、synchronized同步和死锁

    参考http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html,考虑了四种情况,讲解清晰

    public class ThreadTest
    {
        public static void main(String[] args)
        {
            Example example = new Example();
    
            Thread t1 = new Thread1(example);
            Thread t2 = new Thread1(example);
    
            t1.start();
            t2.start();
        }
    
    }
    
    class Example
    {
        public synchronized void execute()
        {
            for (int i = 0; i < 10; ++i)
            {
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                System.out.println("Hello: " + i);
            }
        }
    
    }
    
    class Thread1 extends Thread
    {
        private Example example;
    
        public Thread1(Example example)
        {
            this.example = example;
        }
    
        @Override
        public void run()
        {
            example.execute();
        }
    
    }

    如果不加synchronized关键字,则两个线程同时执行execute()方法,输出是两组并发的。

    如果加上synchronized关键字,则会先输出一组0到9,然后再输出下一组,说明两个线程是顺次执行的。

    4.5、wait()、notify()

    参考http://www.cnblogs.com/mengdd/archive/2013/02/20/2917956.html

    wait()方法使得当前线程必须要等待并释放所有锁,等到另外一个线程调用notify()或者notifyAll()方法。

    notify()方法会唤醒一个等待当前对象的锁的线程。如果多个线程在等待,它们中的一个将会选择被唤醒。这种选择是随意的,和具体实现有关。(线程等待一个对象的锁是由于调用了wait方法中的一个)

    实例:利用两个线程,对一个整形成员变量进行变化,一个对其增加,一个对其减少,利用线程间的通信,实现该整形变量0101这样交替的变更。

    NumberTest
    
    public class NumberHolder
    {
        private int number;
    
        public synchronized void increase()
        {
            if (0 != number)
            {
                try
                {
                    wait();
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
    
            // 能执行到这里说明已经被唤醒
            // 并且number为0
            number++;
            System.out.println(number);
    
            // 通知在等待的线程
            notify();
        }
    
        public synchronized void decrease()
        {
            if (0 == number)
            {
                try
                {
                    wait();
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
            }
    
            // 能执行到这里说明已经被唤醒
            // 并且number不为0
            number--;
            System.out.println(number);
            notify();
        }
    
    }
    
    
    
    public class IncreaseThread extends Thread
    {
        private NumberHolder numberHolder;
    
        public IncreaseThread(NumberHolder numberHolder)
        {
            this.numberHolder = numberHolder;
        }
    
        @Override
        public void run()
        {
            for (int i = 0; i < 20; ++i)
            {
                // 进行一定的延时
                try
                {
                    Thread.sleep((long) Math.random() * 1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
                // 进行增加操作
                numberHolder.increase();
            }
        }
    
    }
    
    
    
    public class DecreaseThread extends Thread
    {
        private NumberHolder numberHolder;
    
        public DecreaseThread(NumberHolder numberHolder)
        {
            this.numberHolder = numberHolder;
        }
    
        @Override
        public void run()
        {
            for (int i = 0; i < 20; ++i)
            {
                // 进行一定的延时
                try
                {
                    Thread.sleep((long) Math.random() * 1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
    
                // 进行减少操作
                numberHolder.decrease();
            }
        }
    
    }
    
    
    
    public class NumberTest
    {
        public static void main(String[] args)
        {
            NumberHolder numberHolder = new NumberHolder();
            
            Thread t1 = new IncreaseThread(numberHolder);
            Thread t2 = new DecreaseThread(numberHolder);
                    
            t1.start();
            t2.start();
        }
    
    }
  • 相关阅读:
    网络知识: 物理层PHY 和 网络层MAC
    Android lowmemorykiller
    devres in linux driver
    spinlock in linux kernel
    JavaWeb图片URL中文乱码
    Linux 里的 2>&1含义
    python脚本linux上后台执行
    linux之定时任务
    python中if not x: 和 if x is not None: 和 if not x is None的使用和区别
    私钥和公钥的区别和联系
  • 原文地址:https://www.cnblogs.com/pjfmeng/p/7807947.html
Copyright © 2020-2023  润新知