Java多线程(一):线程与进程

1.线程和进程

1.1 进程

进程是操作系统的概念,我们运行的一个TIM.exe就是一个进程。

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体

1.2 线程

线程是依附于进程而存在的,每一个线程必须有父进程;
线程拥有自己的堆栈、程序计数器和局部变量,线程和其他的线程共享进程的系统资源;
进程不能共享内存,而线程之间可以轻松地共享内存

2.多线程的意义

2.1 发挥多核处理器最大性能

如一个四核处理器去运行单线程任务,一个核心只能运行一个线程,那么三个核心的性能就会被浪费。再如服务器32核CPU运行一个单线程任务,31个核心在“偷懒”,大大地浪费了服务器性能;
比如博主的电脑CPU是i7 6700HQ,四核八线程。该CPU用到了超线程技术。简单地说,一个单核心的处理器,去模拟出双核心的环境,但这并非能够把处理器的效能提升双倍,原因在于实体的核心始终只有一个,而效能有约百分之二十至三十增长。
我们可以理解成阉割版八核处理器,难道买不起八核,还买不起八线程处理器吗?

2.2 发挥单核处理器最大性能

如果进程是单线程的,它在等待某个I/O操作完成,此时处理器处于空闲状态;如果进程是多线程的,一个线程在等待某个I/O操作完成的时候,另外一个线程可以执行。
单核处理器执行多线程的情况

1.单核CPU同一时间,CPU只能处理1个线程,只有1个线程在执行
2.多线程同时执行:是CPU快速的在多个线程之间的切换
3.CPU调度线程的时间足够快,使我们产生错觉,多线程“同时”执行
4.如果线程数非常多,CPU会在n个线程之间切换,消耗大量的CPU资源,每个线程被调度的次数会降低,线程的执行效率降低

3.创建线程

3.1 继承Thread

继承Thread,重写run方法。

public class MyThread00 extends Thread{
    public void run()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在运行!");
        }
    }


    public static void main(String[] args)
    {
        MyThread00 mt0 = new MyThread00();
        //启动线程
        mt0.start();

        //main线程
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在运行!");
        }
    }
}

start方法:
调用start方法Java虚拟机会启动run方法;
一个线程不能多次调用start方法;
死去的线程不能被重启;
执行结果如下:

main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
main在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
......

线程交替执行,不会按照固定顺序执行,每次执行的结果都不一致。

3.2 实现Runnable

实现Runnable接口,重写run方法;有利于代码解耦。

public class MyThread01 implements Runnable
{
    public void run()
    {
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在运行!");
        }
    }

    public static void main(String[] args)
    {
        MyThread01 mt0 = new MyThread01();
        Thread t = new Thread(mt0);
        //启动线程
        t.start();
        //main线程
        for (int i = 0; i < 50; i++)
        {
            System.out.println(Thread.currentThread().getName() + "在运行!");
        }
    }
}

执行结果类似于3.1

3.3 实现Callable

实现Callable创建线程,重写call方法,该方法可以返回值和抛出异常

扫描二维码关注公众号,回复: 6557138 查看本文章
public class MyThread03 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("计算处理中...");
        Thread.sleep(3000);
        return 1;
    }

    public static void main(String[] args) {
        //构建任务
        MyThread03 t = new MyThread03();
        //执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果
        FutureTask<Integer> task = new FutureTask<Integer>(t);
        //启动线程
        new Thread(task).start();
        //获取结果
        try {
            Integer integer = task.get(5000,TimeUnit.MILLISECONDS);
            System.out.println("线程执行结果:"+integer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果如下

计算处理中...
线程执行结果:1

我们获取到了call方法的返回值,继承Thread和实现Runnable方式创建线程无法获得返回值

猜你喜欢

转载自www.cnblogs.com/Java-Starter/p/11057987.html
今日推荐