多线程(一)

并发编程:现如今电脑都支持同一时间运行多个程序了,那么并发编程也就成为了刚需.

并发编程的作用:提升效率.所谓人多力量大,一群人干活肯定比一个人干活要快不少.

各种语言都是如何实现并发编程的:

     

java实现并发编程:标准库中提供了Thread类,通过Thread就能够实现多线程.其实操作系统本身就提供了一组API,是C语言风格的,因为操作系统本身就是C/C++写的,所以提供的事C语言风格的也就不奇怪了.但java本身的特性就是为了方便,统一而生,如果换了个系统又要学习一套新的API就太麻烦了,所以java就索性直接把各个系统提供的用于并发编程的API都封装成了Thread类,这样的话就只用学习Thread类就可以应付各种操作系统了,也就降低了程序员的学习成本.

创建Thread类的几种基本方法:

 第一种方法:

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class Demo {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
    }
}

第二种方法:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

第三种方法:

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        };
        t.start();
    }
}

第四种方法:

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
        t.start();
    }
}

第五种方法:

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("hello thread");
        });
        t.start();
    }
}

接下来我们解析一下第一种方法的代码:

 对于第二种方法里的Runnable:

sleep方法:sleep方法可以让线程进入阻塞状态,也就是暂时不会被cpu调度执行.

演示:假如我执行下面这串代码,创建了个线程,且这个线程在无限循环打印这个hello thread字符串,会非常快.

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("hello thread");
            }
        });
        t.start();
    }
}

如果我想让他慢一点,隔个1s钟打印一次,就可以用sleep方法了.sleep方法里的参数是时间,单位是ms.

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true){
                System.out.println("hello thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}

sleep方法是属于线程的,哪个线程调用它,哪个线程就进入阻塞状态.

一个进程至少有一个线程就是main方法线程.

两个线程并发执行,都调用sleep方法进入阻塞状态,且时间相同,再次唤醒先执行哪个线程是不确定的,这是由操作系统决定的.因此这两个线程相当于抢占式执行.这也会带来一些麻烦.因为有的时候我们是希望线程按照我们所预期的顺序来执行的。

解决方法:使用wait()和notify().

既然多线程比顺序执行执行效率高,那我们就来试验一下.分别创建两个方法,方法一使用顺序执行,方法二使用多线程执行.这两个方法的目的就是自增到10_0000_0000.看看谁的执行时间更短.

public class Demo {
    private static long num = 10_0000_0000L;
    public static void ser() {
        long begin = System.currentTimeMillis();
        int a = 0;
        for (long i = 0; i < num; i++) {
            a++;
        }
        for (long i = 0; i < num; i++) {
            a++;
        }
        long end = System.currentTimeMillis();
        long time = end - begin;
        System.out.println(time);
    }
    public static void mul() {
        long begin = System.currentTimeMillis();
        Thread t1 = new Thread(() -> {
            for (long i = 0; i < num; i++) {
                i++;
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            for (long i = 0; i < num; i++) {
                i++;
            }
        });
        t2.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        long time = end - begin;
        System.out.println(time);
    }
    public static void main(String[] args) {
        ser();
//        mul();
    }
}

当我调用ser()方法也就是只有一个线程,执行时间为500ms左右,但当我调用mul()方法也就是两个线程同时工作时,执行时间为200多ms.这样一比较就可以明显的得出一个结论,多线程效率是更高的.但要注意一点的是.你要计算的数据必须要够大.因为本身创建线程也是要时间的.如果你计算这个东西只用20ms,而创建两个线程就需要60ms,那肯定就不如直接使用串行执行了.本身多线程就是用来执行较大计算的.

举个例子,你今天要搬1000块砖,那肯定叫多几个人来搬,搬得快一点,那如果只要搬20块砖,那你就直接自己搬就完了呗,因为你要去叫人也是花费时间的,等你叫来人,20块砖早搬完了.

线程等待join()方法:join方法是用来控制执行顺序的,当执行到这个方法后,当前线程会进入阻塞状态,直到调用的线程执行完毕后才会继续执行下面的代码.因为在刚才计算时间的代码其实是在main这个主线程里的,也就是说主线程和其他的几个线程是并发执行的,如果不使用join方法,当创建完线程之后,计算时间这个代码也就执行完毕,那肯定是不对的.

join方法里的参数是时间,单位是ms,可以写也可以不写,当不写时就意味着死等.直到t线程结束才继续执行下面的代码

如果写了,比如写了1000ms也就是1s后如果t线程还没执行完毕主线程也不管了直接执行下面的代码.

</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值