复习并发编程的基础知识(一)

目录

进程和线程

并发和并行

 如何创建一个线程?

1,继承Thread类

 2,实现Runnable接口

         3. Callable<>接口

线程Thread类的一些重要方法

 守护线程:


时间长了,并发编程的基础知识总忘,来记录一下:

进程和线程

进程:资源分配的最小单元,什么是资源?CPU,内存,网卡等等

线程:进程中的一个实体,不能单独存在,依赖进程存在。CPU调度的最小单元。

并发和并行

并发:单位时间内,多个任务交替执行。

 并行:同一时刻,每个任务同时执行。多核CPU可以实现并行。

 如何创建一个线程?

1,继承Thread类
package cn.tulingxueyuan.xiaoshanshan.base;

public class UseThread {

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }

}

class MyThread extends Thread{
    @Override
    public void run() {
        //要执行的代码
        System.out.println("hello ,Thread");
    }
}
2,实现Runnable接口
package cn.tulingxueyuan.xiaoshanshan.base;

public class UseRunnable {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable); // Runnable接口也要借助Thread类才能启动
        thread.start();
    }

}

class MyRunnable implements Runnable{
    @Override
    public void run() {
        // 要执行的代码
        System.out.println("hello ,Runnable");
    }
}

其实Thread类也实现了Runnable接口

我们在启动一个java进程的时候,main()是主线程,在main()方法中又启动了子线程,当主线程运行结束了不意味着进程就结束了,所有线程结束了进程才结束。在main线程中启动一个子线程Thread-0,主线程不会因为有子线程的执行而阻塞,main线程和线程Thread-0会并行执行。也就是说子线程和主线程之前是异步执行的。

如下图程序中,当运行该程序的时候,控制台(Terminal中)输入jconsole,可以查看线程的情况,当main()方法执行完成之后会退出,Thread-0会继续执行。当Thread-0执行结束以后,会卡死或者断开。

package cn.tulingxueyuan.xiaoshanshan.base;

public class CatThreadDemo {


    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();
        for(int  i =0 ;i<60;i++){

            System.out.println(i +", 执行线程名"+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }


}
class Cat extends Thread{

    int times = 0;

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        while(true){

            System.out.println("喵喵,我是一只小猫猫~" + (++times) + "线程名称:" + name);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(times == 80){

                break ;
            }
        }
    }
}

 

3. Callable<>接口

(面试的时候如果问启动线程有几种方法,这种方式其实不能算是创建线程的方法,但是可以作为补充,详细看后面的内容)

Thread类的run方法和Runnable接口的run方法都是返回的空值,那么想得到一个线程的运行结果怎么办呢?

用Callable接口。

 那这个结果怎么拿到呢?阻塞吗?那么线程异步又有什么用呢?为了解决这个问题。JDK又为我们提供了一个类——Future<>接口(优势JUC包中的类,看看JUC多么重要)

 但是Future是个接口,我们主要用这个接口的get()方法,怎么用呢?我们每用一次就去实现一次吗?

不是的,JUC又为我们提供了一个FutureTask类

 Callable怎么传给Thread呢?没有这种方法啊!怎么办呢?将Callable包装成一个FutureTask执行

FutureTask由于是Runnable的子类,可以交给Thread类启动了。

package cn.tulingxueyuan.xiaoshanshan.base;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable());
        new Thread(futureTask).start();
        System.out.println(futureTask.get()); // get阻塞了

        System.out.println("主线程结束");
    }

    static class MyCallable implements Callable<Integer>{

        private int count ;

        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            for(int i = 0;i<100;i++){
                count ++ ;
            }
            System.out.println(Thread.currentThread().getName() + "线程结束,结果是:"+count);
            return count;
        }
    }
}

这里就有一个面试题:新启动一个线程有几种方式?答案:官方给出的是:两种。

根据Thread类写在源码上的注释,其实就两种:一种是继承Thread类,另外一种是实现Runnable接口。

线程Thread类的一些重要方法

start()方法:一个线程只有调用这个方法后,才能真正和操作系统的线程挂钩,

底层是调用了start0()方法,这个方法是native方法,即本地方法,底层是C或者C++实现的,是JVM来调用的,真正实现了多线程。

run()方法:这个方法中是要写的代码逻辑

setName()设置线程名称

getName()得到线程名称

sleep()睡眠,不会释放锁 Thread类调用的静态方法

interrupt()中断方法,不是终止方法

yiled()静态方法,礼让方法,不一定礼让成功,在Cpu资源比较紧张的时候,礼让的效果比较明显

join()线程的插队(这里有个面试题:有三个线程:t1,t2,t3,如何保证t3在t2之前完成,t2在t1之前完成)

package cn.tulingxueyuan.xiaoshanshan.base;

public class UseJoin {


    public static void main(String[] args) {
        JoinThread t1 = new JoinThread();
        JoinThread t2 = new JoinThread();
        JoinThread t3 = new JoinThread();
        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.setT(t2);
        t2.setT(t3);
        t1.start();
        t2.start();
        t3.start();

    }

}

class JoinThread extends Thread{
    Thread t ;

    public void setT(Thread t) {
        this.t = t;
    }

    @Override
    public void run() {

        if(null!=t){
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println( "线程:" + Thread.currentThread().getName()  +  "执行我的逻辑...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

 守护线程:

守护线程服务于用户线程,当用户线程结束的时候,守护线程也结束了

package cn.tulingxueyuan.xiaoshanshan.base;

public class DaemonThread {

    public static void main(String[] args) throws InterruptedException {
        MyDaemonThread myDaemonThread = new MyDaemonThread();
        myDaemonThread.setDaemon(true);
        myDaemonThread.start();

        for (int i =0;i<10;i++){
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + "打印出:" +i);
        }
    }
}

class MyDaemonThread extends Thread{

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "打印出:" + Math.random()*100+1);
        }
    }
}

看,main线程结束了,守护线程Thread-0也结束了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值