Java多线程学习

1.进程和线程的区别?

  • 进程

    • 是操作系统分配资源的基本单位。
    • 一个程序运行就会创建一个进程。
    • 进程通常是独立存在的,拥有自己独立的资源。
    • 多个进程不能共享资源,每个进程都有自己的堆、栈、虚存空间等,进程之间不会互相干扰
  • 线程

    • 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
    • 一个进程至少包含一个线程,也可以多个,线程属于进程。
    • 一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。
  • 区别

    • 进程是由操作系统管理,线程是由编程的人员编写管理。

    • 进程是正在运行的程序,进程中包含线程,线程属于进程。

    • 进程是操作系统分配资源的基本单位,而线程是操作系统调度的基本单位。

    • 多个进程间不能共享资源,而线程可以共享进程资源文件(堆和方法区)。

在这里插入图片描述

2.实现线程有哪些方式?

  • 继承Thread类
    • 继承 Thread 类 extends Thread
    • 重写run()方法
    • 调用线程类的start()方法
public class Thread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                //sleep()让程序暂停一段时间,单位是毫秒
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(getName() + ": " + i);
        }
    }
}

public static void main(String[] args) {
        Thread1 thread1 = new Thread1("线程一");
   		thread1.start();
    }

  • 实现Runnable接口
    • 实现Runnable接口, 重写run方法
    • 创建一个Thread对象,构造方法参数是实现了Runnable接口类的对象
    • 调用Thread对象的start方法启动线程
public class Thread2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }           					 				System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

public static void main(String[] args) {
        Thread2 t1 = new Thread2("线程一");
   		Thread t = new Thread(t1);
    	t.start();
    }
  • 实现Callable接口
    • 实现Callable接口,重写call方法
    • 创建FutureTask对象,构造方法是实现了Callable接口的对象
    • 创建Thread的对象, 构造方法的参数是FutureTask的对象
    • 调用start()方法启动线程
import java.util.concurrent.Callable;

public class Thread3 implements Callable<String> {

    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(1);
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }

        return Thread.currentThread().getName();
    }
}

public static void main(String[] args) {
        Thread3 call1 = new Thread3();
        //创建FutureTask对象,构造方法的参数是实现了Callable接口的对象
        FutureTask<String> futureTask1 = new FutureTask<>(call1);
        //创建Thread对象,构造方法的参数FutereTask对象
        Thread t1 = new Thread(futureTask1);
        //启动线程
        t1.start();
    }

3.简述线程的生命周期?

线程的生命周期分为五个阶段:创建、就绪、运行、阻塞、结束。

  • 创建

    新创建了一个线程对象,还未调用start()方法。 如 Thread thread = new Thread();。

  • 就绪

    线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中 获取cpu 的使用权 。

  • 运行

    运行状态,当线程被激活执行,这时候线程就是运行状态,执行run()方法。
    也有可能因为cpu时间片用完,或是其他方法被调用,回到就绪状态。

  • 阻塞

    阻塞状态,暂停运行, 正在运行的线程遇到wait(),sleep(),或者是同步资源被占用时会被阻塞。

    被wait()阻塞的线程需要被特定的方法唤醒才能重新回到就绪状态。而被sleep()阻塞的线程只需要等待sleep时间结束就可以重新回到就绪状态。

  • 结束

    终止状态,run()正常执行完毕,就进入到终止状态,线程生命周期就结束。

4.什么是并发?并发会导致什么问题?怎么解决并发的问题?

  • 并发

    多个线程在执行任务的时候,同时(并行)访问同一个资源(方法或者属性)。

  • 并发产生的问题

    可能导致数据的不一致,错乱。

  • 怎么解决并发问题

    给属性或方法添加synchronized(同步)关键字,就是给资源上锁,有线程使用时锁住,使用完就解锁。

5.同步和异步的区别?

  • 同步

    同步是线程按顺序执行,就是当A请求一个资源的时候,这个资源正在被B使用,那么A就必须要等待,等到B使用完了A才能请求到。

  • 异步

    异步是多个线程同时进行,就是当A请求一个资源的时候,这个资源正在被B使用,A不需要等也可以请求到。

  • 区别

    • 同步需要等待,异步不需要等待。
    • 同步是安全的,异步不安全可能会导致产生并发问题。

6.死锁形成的条件是什么? 怎样避免死锁?

  • 死锁

    两个线程相互等待对方释放它锁定的资源,两个线程都没有办法继续执行,程序就一直处于等待状态,不会结束,也不能成功运行,这种现象就是死锁。

  • 死锁形成的条件

    • 互斥条件:一个资源只能被一个线程占有,当这个资源被占有后其他线程就只能等待
    • 不可剥夺条件:当一个线程不主动释放资源时,此资源一直被拥有线程占有
    • 请求并持有条件:线程已经拥有了一个资源后,又尝试请求新的资源
    • 环路(循环)等待条件:产生死锁一定是发生了线程资源环形链,就是A线程持有资源1等待资源2, B线程持有资源2等待资源1。
  • 避免死锁

    • 以相同的顺序去所锁定资源
    • 另外建立一个锁的对象,只锁一个对象,不要锁多个对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值