java多线程-初探(一)

啥是多线程?跟进程又是啥关系?

比方说:我去洗手,洗完手去吃饭。

进程(Processor)

洗手跟吃饭是两个进程。

线程(Thread)

在洗手的进程里,我同时听歌,还唱歌。那这里洗手是一个进程,听歌跟唱歌是两个线程。

在吃饭的进程里,我同时听歌,还唱歌。那这里吃饭是一个进程,听歌跟唱歌是两个线程。

吃饭跟洗手两个进程之间的线程互不干扰,同个进程之间的线程存在锁、等待、唤醒等等等机制。

多线程:同一个进程内做多件事,每件事是一个线程

这里创建一个普通java项目。

单线程示例

以吃饭为例,只有听完歌才能唱歌,无法边听边唱。

class Main

public class Main {

    /**
     * 吃饭
     * @param args
     */
    public static void main(String[] args) {
        Song song = new Song();
        while (!song.listenIsZero())
            song.doThing("listen") ;
        while (!song.singIsZero())
            song.doThing("sing") ;
        System.out.println("执行完成!");
    }
}

class Song

public class Song {

    // 待唱的歌曲数量
    private int singNum = 5 ;

    // 待听的歌曲数量
    private int listenNum = 5 ;

    public boolean singIsZero(){
        return singNum == 0 ;
    }

    public boolean listenIsZero(){
        return listenNum == 0 ;
    }

    public void doThing(String thing){
        switch (thing){
            case "sing" : doSing(); break;
            case "listen" : doListen(); break;
        }
    }

    public void doSing(){
        try {
            // 唱歌需要时间,加时间能体现多线程的效果
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("唱了一首歌,剩余:" + singNum-- +"首未唱");
        if (singIsZero()) System.out.println("唱完了!");
    }

    public void doListen(){
        try {
            // 听歌需要时间,加时间能体现多线程的效果
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("听了一首歌,剩余:" + listenNum-- +"首未听");
        if (listenIsZero()) System.out.println("听完了!");
    }

}

执行结果

多线程示例(继承Thread类)

可以在吃饭的进程里,边听歌边唱歌。同时进行。

创建一个类负责听歌或者唱歌,继承Thread,重写run函数。

建立两个线程,都start之后可以观察到两个线程同时调用doThing函数。

class Main

public class Main {

    /**
     * 吃饭
     * @param args
     */
    public static void main(String[] args) {
        // 单线程示例
        /*Song song = new Song();
        while (!song.listenIsZero())
            song.doThing("listen") ;
        while (!song.singIsZero())
            song.doThing("sing") ;*/

        // 多线程示例
        SongThread listen = new SongThread("listen", new Song());
        SongThread sing = new SongThread("sing", new Song());
        // 启动两个线程
        listen.start();
        sing.start();
        System.out.println("执行完成!");
    }
}

class SongThread

public class SongThread extends Thread{

    private Song song ;

    private String thing ;

    public SongThread(String thing, Song song){
        this.song = song;
        this.thing = thing;
    }

    public void run(){
        switch (thing){
            case "listen" : while (!song.listenIsZero()) song.doListen(); break;
            case "sing" : while (!song.singIsZero()) song.doSing(); break;
        }
    }

}

执行结果

多线程示例(实现Runnable接口)

创建一个类实现Runnable接口,然后new Thread的时候将实现类传参之后start。

Thread与Runnable的关系:Thread类实现了Runnable接口。

class Main

public class Main {

    /**
     * 吃饭
     * @param args
     */
    public static void main(String[] args) {
        // 单线程示例
        /*Song song = new Song();
        while (!song.listenIsZero())
            song.doThing("listen") ;
        while (!song.singIsZero())
            song.doThing("sing") ;*/

        /*// 多线程示例 Thread
        SongThread listen = new SongThread("listen", new Song());
        SongThread sing = new SongThread("sing", new Song());
        // 启动两个线程
        listen.start();
        sing.start();
        System.out.println("执行完成!");*/

        // 多线程示例 实现Runnable接口
        SongRunnable listen = new SongRunnable("listen", new Song());
        SongRunnable sing = new SongRunnable("sing", new Song());
        // 启动两个线程
        new Thread(listen).start();
        new Thread(sing).start();
    }
}

class SongRunnable

public class SongRunnable implements Runnable{

    private Song song ;

    private String thing ;

    public SongRunnable(String thing, Song song){
        this.song = song;
        this.thing = thing;
    }

    public void run(){
        switch (thing){
            case "listen" : while (!song.listenIsZero()) song.doListen(); break;
            case "sing" : while (!song.singIsZero()) song.doSing(); break;
        }
    }

}

执行结果

java多线程-初探(二)

实际业务应用场景举例

1.后台需要定时给数据库100w个用户发送提醒邮件。

 启动两个线程分别给50w个用户发邮件。

2.不影响用户情况下记录用户操作日志(异步)

 启动一个线程去单独执行记录日志的操作。

猜你喜欢

转载自blog.csdn.net/wkh___/article/details/84785760