多线程

来源:互联网 发布:淘宝矜贵芳旗舰店 编辑:程序博客网 时间:2024/05/21 17:28

在编程中,多线程的意思是某个程序同时多个任务,这样的每一个任务则称为一个线程。线程这部分涉及的知识非常多,在实际开发的应用也是非常重要,这里将介绍基本的部分。

概念

线程:操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中实际运作单位。
进程:计算机中已运行程序的实体。进程本身不会运行,是线程的容器。
并行与并发:
* 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
* 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。[1]

实现多线程的几种基本方式

1、继承Thread类

public class Test02 extends Thread{    private String name;    public Test02(String name) {        this.name = name;    }    @Override    public void run() {        for(int i=0; i<100; i++){            System.out.println(name + i);        }    }    public static void main(String[] args) throws InterruptedException {        Test02 test1 = new Test02("one-->");        Test02 test2 = new Test02("two-->");        test1.start();        test2.start();    }}

2、实现Runnable接口

public class Test01 implements Runnable{    private String name;    public Test01(String name){        this.name = name;    }    @Override    public void run() {        for(int i=0; i<100; i++){            System.out.println(name+"--->"+i);        }    }    public static void main(String[] args) {        Test01 test1 = new Test01("one");        Test01 test2 = new Test01("two");        Thread thread1 = new Thread(test1);//使用thread类执行start方法        Thread thread2 = new Thread(test2);        thread1.start();        thread2.start();    }}

3、使用Callable和Future接口创建线程

public class Test03 implements Callable<Integer>{    @Override    public Integer call() throws Exception {        for(int i=0; i<100; i++){            System.out.println(Thread.currentThread().getName()+"--->"+i);        }        return null;    }    public static void main(String[] args) {        Test03 t1 = new Test03();        Test03 t2 = new Test03();        FutureTask<Integer> task1 = new FutureTask<>(t1);        FutureTask<Integer> task2 = new FutureTask<>(t2);        new Thread(task1, "新建线程1").start();        new Thread(task2, "新建线程2").start();    }}

线程状态

使用getState()方法可获取当前线程的状态(枚举类型),各种状态如下:

  • New(新生)
    当new一个新的线程时,线程还没开始运行时,状态是new
public class Test {    public static void main(String[] args) {        Thread thread = new Thread();        System.out.println(thread.getState());    }}

输出
NEW

  • Runnable(可运行)
    线程调用start执行时
public class Test {    public static void main(String[] args) {        Thread thread = new Thread(new Runnable() {            public void run() {                for(int i=0; i<100; i++){                    System.out.println("i is "+i);                }            }        });        thread.start();        System.out.println(thread.getState());    }}

输出
RUNNABLE
i is 0
i is 1

i is 99

  • Blocked(被阻塞)
    当一个线程试图获取一个内部的对象锁(而不是java.util.concurrent库中的锁),而该锁被其他线程持有,则该线程进入阻塞状态。
public class Test {    final Object lock = new Object();    class Example implements Runnable{        private String name;        public Example(String name) {            this.name = name;        }        @Override        public void run() {            //同步代码块            synchronized (lock) {                for(int i=0; i<100; i++){                    System.out.println(name+": i is "+i);                }            }        }    }    public static void main(String[] args) {        Example example1 = new Test().new Example("test1");        Example example2 = new Test().new Example("test2");        Thread thread1 = new Thread(example1);        Thread thread2 = new Thread(example2);        thread1.start();        thread2.start();        System.out.println(thread1.getState());        System.out.println(thread2.getState());    }}

输出
RUNNABLE
test1: i is 0
test2: i is 0
test1: i is 1
BLOCKED
test1: i is 2

  • Waiting(等待)
    等待状态,释放自身的锁进入Waiting状态并加入线程等待队列
public class Test {    public synchronized void testMethod(){        try {            this.wait();            System.out.println("waiting closed.");        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws InterruptedException {        Thread thread1 = new Thread(new Runnable() {            public void run() {                new Test().testMethod();            }        });        thread1.start();        Thread.sleep(10);//主线程休眠,转而去执行子进程        System.out.println(thread1.getState());    }}

输出
WAITING
waiting closed并不会输出

  • Timed waiting(计时等待)
    this.wait();加上等待时间就会进入计时等待状态,例如this.wait(3000);等待三秒输出内容
    TIMED_WAITING
    waiting closed.

  • Terminated(被终止)
    run方法执行结束线程终止

public class Test {    public static void main(String[] args) throws InterruptedException {        Thread thread = new Thread(new Runnable() {            public void run() {                System.out.println("run success");            }        });        thread.start();        Thread.sleep(100);        System.out.println(thread.getState());    }}

线程管理

  1. sleep方法
    static void sleep(long millis)
    让当前正在运行的线程休眠一段时间
    sleep是一个静态方法,不要用实例化的线程对象调用,其作用的是当前正在运行的线程。
    Thread.sleep(2000);表示让当前线程休眠2秒,这里的2秒并不是准确的时间段,因为线程是由系统控制,实际时间可能大于2秒。

  2. yield方法
    static void yield()
    暂停当前正在执行的线程,重新进入就绪状态,这也是和sleep方法的区别的地方。如果有其他的可运行线程具有至少与此线程同样高的优先级,那么这些线程接下来会被调度。

  3. join方法
    合并线程。等待终止指定的线程,让主线程等待子线程结束之后再执行

public class Test {    public static void main(String[] args) throws InterruptedException {        Thread thread1 = new Thread(new Runnable() {            public void run() {                for(int i=0; i<100; i++){                    System.out.println("one--"+i);                }            }        });        Thread thread2 = new Thread(new Runnable() {            public void run() {                thread1.start();                try {                    thread1.join();                } catch (InterruptedException e) {                    e.printStackTrace();                }                for(int i=0; i<100; i++){                    System.out.println("two--"+i);                }            }        });        thread2.start();    }}

thread1在thread2中启动,为thread2子线程,调用join,等待thread1执行结束再执行thread2,相当于把两线程合并了。
void join(long millis)
join重载方法带参数,在指定时间段子线程未执行完将重新进入就绪状态,等待cpu调度。

  1. notify和notifyAll方法
    notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。
    notifyAll 会唤醒所有等待(对象的)线程。
public class Test {    public synchronized void testMethod(){        try {            System.out.println("thread start.");            this.wait();            System.out.println("waiting closed.");        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public synchronized void notifyMethod(){        this.notifyAll();    }    public static void main(String[] args) throws InterruptedException {        Test test = new Test();        Thread thread1 = new Thread(new Runnable() {            public void run() {                test.testMethod();            }        });        Thread thread2 = new Thread(new Runnable() {            public void run() {                test.notifyMethod();                System.out.println("唤醒线程.....");            }        });        thread1.start();        Thread.sleep(1000);        System.out.println(thread1.getState());        thread2.start();    }}

输出
thread start.
WAITING
唤醒线程.....
waiting closed.

  1. interrupted和isInterrupted
    Interrupted方法是一个静态方法,它检测当前的线程是否被中断。而且,调用interrupted方法会清除该线程的中断状态。
    另一方面,isInterrupted方法是一个实例方法,可用来检验是否有线程被中断。调用这个方法不会改变中断状态。

  2. setPriority和getPriority
    void setPriority(int newPriority)
    设置线程的优先级。优先级必须在Thread.MIN_PRIORITY 与Thread.MAX_PRIORITY之
    间。一般使用Thread.NORM_PRIORITY 优先级。
    final int getPriority()
    获取线程的优先级

  3. 结束线程
    Tread中有stop方法,但改方法已经过时,不推荐使用。要结束线程,可设置标志来实现。

public class Test {    class TestTread implements Runnable{        private boolean flag;        private void stopThread() {            this.flag=true;        }        @Override        public void run() {            for(int i=0; i<1000 && !flag; i++){                System.out.println("i is "+i);            }        }    }    public static void main(String[] args) throws InterruptedException {        TestTread test = new Test().new TestTread();        Thread thread1 = new Thread(test);        thread1.start();        Thread.sleep(3);//休眠延时        test.stopThread();    }}

输出一段i的值之后当执行stopThread方法线程就结束了。

0 0