美文网首页
Java进阶-线程

Java进阶-线程

作者: 指尖轻敲 | 来源:发表于2018-12-02 00:20 被阅读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。我们也可以设置线程名字。注释代码放开之后打印的就是永琪和小燕子。

    • getName():获取当前线程对象的名字。

    • setName():设置线程的名字。

    • start():开始执行线程

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

    线程休眠

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

    网上找的.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可以避免单继承的限制,也可以实现多个线程共享资源。

    相关文章

      网友评论

          本文标题:Java进阶-线程

          本文链接:https://www.haomeiwen.com/subject/kwpiqqtx.html