Java进阶-线程

2018-12-02  本文已影响0人  指尖轻敲

进程和线程


这两个概念其实还是很好区分的,我们每一个应用程序其实就可以说是一个进程,进程是由系统创建的;在每个进程之中又有多条线程,线程是依赖进程而存在的。
java是无法直接调用系统程序的,只能调用C/C++写好的程序去实现多线程。

多线程的实现


要实现多线程有两种方法,一个是继承Thread类,并重写run方法。还有一个是实现Runnable接口,该接口有效的避免了java单继承的局限性,适合多个相同的程序代码去处理同一个资源的情况。
我们来依次看一下两种实现方法:

Thread类

要实现多进程就要继承Thread类并且重写run方法,这里先看一个最简单的例子。

public class ThreadDemo extends Thread{
    public static void main(String[] args){
        ThreadDemo td = new ThreadDemo();
        ThreadDemo td2 = new ThreadDemo();
//        td.setName("永琪");
//        td2.setName("小燕子");
        td.start();
        td2.start();
    }
    public void run(){
        System.out.println(getName());
    }
}
/*
Thread-0
Thread-1

永琪
小燕子

当线程对象执行的时候就会调用run方法打印出当前线程对象的名字,默认就是Thread-x。我们也可以设置线程名字。注释代码放开之后打印的就是永琪和小燕子。

这里线程的执行顺序是随机的,并不是依次执行。多执行几次或者执行次数多一些会发现没有顺序规律。

线程休眠

写到这里不由得想到前几的天看到的那个段子

网上找的.jpg

万万没想到竟然可以把休眠用的如此清新脱俗,“这么有想法的程序员怎么能开除?”。休眠就是让程序暂停执行直到指定的时间之后再开始。我们来修改一下上面的run方法:

public void run(){
    int a = 0;
    while (a < 10){
        System.out.println(getName());
        a++;
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }

}

在run方法里加一个循环,让getName()执行十次,每次打印之后加一个休眠1秒的操作。这里休眠方法需要捕获异常。可以看到程序会在打印一次“小燕子”“永琪”(也可能是永琪、小燕子)之后暂停一秒,在继续打印,如此重复十次。

Runnable接口

同样实现Runnable接口的线程启动时也会先调用run方法。但是在Runnable接口中没有提供getName方法,我们需要通过Thread.currentThread().getName()来获取进程名。
在创建进程时需要把Runnable的一个实例传递到Thread类的构造方法中,第二个参数接收一个进程名。

// 实现Runnable接口:
public class RunnableDemo implements Runnable {
    public void run(){
        for (int i = 0; i<10 ;i++){
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }
}
// 创建线程
Thread thread = new Thread(new RunnableDemo(), "实现接口的线程");
thread.start();

常用方法

1. 加入线程

如果我不想让这几个线程交叉执行,我想让“永琪”线程执行完再执行“小燕子”线程和接口线程。这里可以使用join()方法(需要捕获异常)。

td.start();
try {
   td.join();
}catch (Exception e){
    e.printStackTrace();
}
2. 停止线程

停止线程难道不是stop吗?还用说吗?是stop没错,不过让线程戛然而止的的效果不推荐使用。一般用不到此方法。
还有一个方法是interrupt(),该方法终止线程状态,并抛出一个InterruptedException异常。

这里我们可以声明一个volatile关键字修饰的变量。被volatile修饰的变量可以保证被每个线程都能读取到最新的值。我们就可以通过改变该变量的值来停止线程。再来修改一下run方法:

volatile boolean isStop = false;
public void run(){
    int a = 0;
    while (!isStop){
        System.out.println(getName());
        if(++a == 8){
            isStop = true;
        }
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}

这样,当执行第8次的时候,isStop 被改为了true,所以run方法内的循环不在执行。停止了线程。

二者区别

Runnable可以避免单继承的限制,也可以实现多个线程共享资源。

上一篇 下一篇

猜你喜欢

热点阅读