Java多线程

线程

1什么是线程

线程总体分两类:用户线程和守护线程。

我们的main方法就是跑在线程中的,其实我们启动的每一个线程都可以看作是一个新的main线程,其中守护线程包含我们的GC线程。

2线程与进程

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。

线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。JVM会给它在栈内存空间中开辟新的空间来执行线程。

简单说来就是,一个进程可能包含多个线程

讲到这里,我们再来认识一下并行和并发

并行,指的是多个程序一起执行,需要依靠多核心处理器,处理器就相当于我们人的大脑,我们没法做到一心二用就是因为我们只有一个大脑,我们在边听歌边写作业的时候,其实并不是同时进行的,我们在同一时刻只能执行一件事情。

并发,就是指多个程序交替执行,我们一边写作业一边听歌就是这种情况,单核处理器就会出现并发的问题,我们不能再一个时刻干很多事情,只能一个一个完成,一个一个推进,每件事情分配的时间完全取决于我们的cpu。

3多线程的实现

我们实现多线程的方法主要有三个

1继承Thread类,重写run方法

package com.fq.onclass526;

public class Example_1 extends Thread{
    String threadID;

    public Example_1(String threadID) {
        this.threadID = threadID;
    }
    public void run() {
        System.out.println("Thread started:" + this.threadID);
        for (int i = 0; i < 6; i++) {
            System.out.println(threadID + " i = " + (i + 1) + "\t");
        }
        System.out.println("Thread stopped:" + this.threadID);
    }
}

package com.fq.onclass526;

public class ThreadTest1 {
    public static void main(String[] args) {
        System.out.println("Starting ThreadTest1");
        Example_1 t1 = new Example_1("Thread1");
        t1.start();
        Example_1 t2 = new Example_1("Thread2");
        t2.start();
        Example_1 t3 = new Example_1("Thread3");
        t3.start();
        System.out.println("ThreadTest1 is done");
     }
}

Starting ThreadTest1
ThreadTest1 is done
Thread started:Thread1
Thread started:Thread3
Thread started:Thread2
Thread3 i = 1	
Thread1 i = 1	
Thread3 i = 2	
Thread3 i = 3	
Thread3 i = 4	
Thread3 i = 5	
Thread2 i = 1	
Thread2 i = 2	
Thread2 i = 3	
Thread3 i = 6	
Thread1 i = 2	
Thread stopped:Thread3
Thread2 i = 4	
Thread1 i = 3	
Thread2 i = 5	
Thread1 i = 4	
Thread2 i = 6	
Thread1 i = 5	
Thread stopped:Thread2
Thread1 i = 6	
Thread stopped:Thread1

Process finished with exit code 0

奇怪不,明明说程序顺序执行,可是为什么

Starting ThreadTest1
ThreadTest1 is done

会打印在一起呢,就是因为多线程的原因,cpu给main线程分配到的时间刚好可以先把main方法执行完,之后再给其他线程分配空间。

在这段代码中其他线程开始的时间分配是怎么样的呢?

我们在执行前并不清楚,只有在结果出来以后才明白

他们的启动的顺序应该是Thread1—>Thread3—>Thread2

这一种方法有一些不足之处,大家想到了吗?

那就是不能多继承,比如我想同时继承Thread类,我又想它继承LinkedList类,那么就无法实现了

2实现Runnable接口,重写run方法

这种方法我们最常使用,但是为什么实现Runnable接口可以实现呢?他只有run方法啊,不能启动线程,只能像lambda表达式一样直接调用run啊,那还是在main线程里面

我们看看Thread的构造方法

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

原来如此,我们可以用一个实现了Runnable接口的类来构造Thread,用Thread的实例对象调用start方法

package com.fq.onclass526;

import java.util.ArrayList;
import java.util.concurrent.Callable;

public class Example11_2 implements Runnable{
    String threadId;

    public Example11_2(String threadId) {
        this.threadId = threadId;
    }

    @Override
    public void run() {
        System.out.print("\n Thread started:"+this.threadId);
        for(int i = 0;i<6;i++)
            System.out.print(" i = "+(i+1)+"\t");
        System.out.print("\n Thread stopped:"+this.threadId);
    }
}

public class ThreadTest2 {
    public static void main(String[] args) {
        System.out.println("Starting ThreadTest1");
        Runnable r1 = new Example11_2("thread1");
        Thread t1 = new Thread(r1);
        t1.start();
        Runnable r2 = new Example11_2("thread2");
        Thread t2 = new Thread(r2);
        t2.start();
        Runnable r3 = new Example11_2("thread3");
        Thread t3 = new Thread(r3);
        t3.start();
        System.out.println("ThreadTest2 is done");
    }
}

Starting ThreadTest1
ThreadTest2 is done

 Thread started:thread1 i = 1	
 Thread started:thread3
 Thread started:thread2 i = 1	 i = 2	 i = 2	 i = 1	 i = 3	 i = 3	 i = 4	 i = 2	 i = 3	 i = 4	 i = 5	 i = 6	 i = 5	 i = 4	 i = 6	
 Thread stopped:thread2
 Thread stopped:thread3 i = 5	 i = 6	
 Thread stopped:thread1

3实现Callable接口,重写call方法

Runnable 和 Callable 接口的区别

其中的方法不同,一个是run,一个是call

call方法有返回值

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Callable任务借助FutureTask运行

Runnable任务借助Thread运行

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值