2024年最新Javva学也学不明白之多线程机制详解。(1),java程序员面试笔试真题与解析

笔者福利

以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。

有了这个,面试踩雷?不存在的!

回馈粉丝,诚意满满!!!




本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

        //获取当前线程t1

        //t2线程执行此方法,当前对象就是t2

        Thread t=Thread.currentThread();

        System.out.println(t.getName()+"线程----->"+i);//t1

         try {

         //休眠一秒

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}

}




运行结果:



main

t1

t2

t2线程----->0

t1线程----->0

t2线程----->1

t1线程----->1

t2线程----->2

t1线程----->2

t2线程----->3

t1线程----->3

t2线程----->4

t1线程----->4

t2线程----->5

t1线程----->5

t2线程----->6

t1线程----->6

t2线程----->7

t1线程----->7

t2线程----->8

t1线程----->8

t2线程----->9

t1线程----->9

Process finished with exit code 0




[]( )2.实现 Runnable 接口

-----------------------------------------------------------------------------



其实 Thread 对象本身就实现了 Runnable 接口,但一般建议直接使用 Runnable 接口来写多线程程序,因为接口会比类带来更多的好处



示例代码(2):



public class ThreadText02 {

public static void main(String[] args) {

    //创建线程

    Thread t=new Thread(new MyRunnable());

    //启动线程

    t.start();

    for (int i = 0; i < 10; i++) {

        System.out.println("主线程----->"+i);

    }

}

}

class MyRunnable implements Runnable{

public void run() {

    for (int i = 0; i < 10; i++) {

        System.out.println("分支线程----->"+i);

    }

}

}




运行结果:



主线程----->0

分支线程----->0

主线程----->1

分支线程----->1

主线程----->2

分支线程----->2

主线程----->3

分支线程----->3

主线程----->4

分支线程----->4

主线程----->5

分支线程----->5

主线程----->6

分支线程----->6

主线程----->7

分支线程----->7

分支线程----->8

分支线程----->9

主线程----->8

主线程----->9




[]( )3.实现线程的第三种方式实(现Callable接口。(JDK8新特性。))

--------------------------------------------------------------------------------------------------



这种方式实现的线程可以获取线程的返回值。(效率低)  

示例代码:



import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.FutureTask;//JUC包下的,属于java并发包,老jdk没有,新特性

public class ThreadText14 {

public static void main(String[] args) {

    FutureTask task=new FutureTask(new Callable() {

        @Override

        public Object call() throws Exception {//call方法相当于run方法,但是有返回值

            System.out.println("call method begin");

            Thread.sleep(1000*2);

            int a=100;

            int b=200;

            return a+b;//(自动装箱)

        }

    });



    Thread ti=new Thread(task);

    //开始

    ti.start();

    //get方法导致当前线程阻塞!!

    try {

        Object obj=task.get();

        System.out.println("线程执行结果--->"+obj);

    } catch (InterruptedException e) {

        e.printStackTrace();

    } catch (ExecutionException e) {

        e.printStackTrace();

    }

    System.out.println("hello world");

}

}




运行结果:



call method begin

线程执行结果—>300

hello world




[]( )三、线程的生命周期

======================================================================



#### []( )线程的生命周期存在五个状态:新建、就绪、运行、阻塞、死亡



![在这里插入图片描述](https://img-blog.csdnimg.cn/20200727160400148.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1pwX2luc2lzdA==,size_16,color_FFFFFF,t_70)



**新建:采用 new语句创建完成  

就绪:执行 start 后  

运行:占用 CPU 时间  

阻塞:执行了 wait 语句、执行了 sleep 语句和等待某个对象锁,等待输入的场合  

终止:退出 run()方法**



[]( )四、多线程并发环境下,数据的安全问题。

================================================================================



*   **什么时候数据在多线程并发的环境下会存在安全问题呢?**



三个条件:①多线程并发②有数据共享③共享数据有修改的行为。



*   **怎么解决线程安全问题呢?**  

    使用线程同步机制:线程排队执行。(不能并发)



[]( )线程同步与线程异步的理解

-------------------------------------------------------------------------



异步编程模型:

	线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1,

	谁也不需要等谁,这种编程模型叫做:异步编程模型。

	其实就是:多线程并发(效率较高。)

	异步就是并发。

同步编程模型:

	线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行

	结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,

	两个线程之间发生了等待关系,这就是同步编程模型。

	效率较低。线程排队执行。

	同步就是排队。



#### []( )线程同步其实是对对象加锁(给对象加锁使用“synchronized”关键字:)



**synchronized有三种写法:**  

①同步代码块



		synchronized(线程共享对象){

			同步代码块;

		}

		线程共享对象必须是多线程共享的数据。

java中,任何对象都有一把锁,是一个标记,让哪个线程排队,让那个线程共享数据




②在实例方法上使用synchronized表示共享对象一定是this并且同步代码块是整个方法体。



③在静态方法上使用synchronized表示找类锁。类锁永远只有1把。



**Java中三大变量:**



实例变量:在堆中。

静态变量:在方法区。

局部变量:在栈中。




> 以上三大变量中:  

> 局部变量永远都不会存在线程安全问题。  

> 因为局部变量不共享。(一个线程一个栈。)  

> 局部变量在栈中。所以局部变量永远都不会共享。



实例变量在堆中,堆只有1个。

静态变量在方法区中,方法区只有1个。

堆和方法区都是多线程共享的,所以可能存在线程安全问题。

局部变量+常量:不会有线程安全问题。

成员变量:可能会有线程安全问题。




#### []( )以后开发中应该怎么解决线程安全问题?



1.尽量使用局部变量代替“实例变量和静态变量”。  

2.如果必须是实例变量,那么可以考虑创建多个对象,这样实例变量的内存就不共享了。  

3.如果不能使用局部变量,对象也不能创建多个,这个时候就只能选择synchronized了。线程同步机制。



#### []( )Java中怎样终止一个线程



使用布尔标记:  

示例代码(3):



public class ThreadText10 {

public static void main(String[] args) {

    MyRunnable4 r = new MyRunnable4();

    Thread t = new Thread(r);

    t.setName("t");

    t.start();

    try {

        t.sleep(1000*5);

    } catch (InterruptedException e) {

        e.printStackTrace();

    }

    //终止线程

    //想要什么时候终止,把标记修改为false就终止!

    r.run=false;

}

}

class MyRunnable4 implements Runnable {

//打一个布尔标记

Boolean run = true;

@Override

public void run() {

    if (run) {

        for (int i = 0; i < 10; i++) {

            System.out.println(Thread.currentThread().getName() + "---->" + i);

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    } else {

        //在这里保存数据!!!

        return;

    }

}

}




[]( )为了预防死锁的出现,面试官说:“请手写一个死锁代码”。

----------------------------------------------------------------------------------------



示例代码(4):



public class ThreadText04 {

public static void main(String[] args) {

    Object o1 = new Object();

    Object o2 = new Object();



    Thread t1 = new MyThread01(o1, o2);

    Thread t2 = new MyThread02(o1, o2);



    t1.start();

    t2.start();



}

}

class MyThread01 extends Thread {

Object o1;

Object o2;



public MyThread01(Object o1, Object o2) {

    this.o1 = o1;

    this.o2 = o2;

}



@Override

public void run() {

    synchronized (o1){

        try {

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        synchronized (o2){



        }

    }

}

}

class MyThread02 extends Thread {

Object o1;

Object o2;



public MyThread02(Object o1, Object o2) {

    this.o1 = o1;

    this.o2 = o2;

}



public void run() {

    synchronized (o2){

        try {

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        synchronized (o1){

            

        }

    }

}

}




[]( )五、守护线程

===================================================================



java语言中线程分为两大类:

	一类是:用户线程

	一类是:守护线程(后台线程)

	其中具有代表性的就是:垃圾回收线程(守护线程)。



**守护线程:所有的用户线程结束生命周期,守护线程才会结束生命周期,只要有一个用户线程存在,那么守护线程就不会结束,例如 java 中著名的垃圾回收器就是一个守护线程,只有应用程序中所有的线程结束,它才会结束。**



**守护线程的特点:**  

一般守护线程是一个死循环,所有的用户线程只要结束,  

守护线程自动结束。



示例代码(5):



/*

守护线程!!

最后

光给面试题不给答案不是我的风格。这里面的面试题也只是凤毛麟角,还有答案的话会极大的增加文章的篇幅,减少文章的可读性

Java面试宝典2021版

最常见Java面试题解析(2021最新版)

2021企业Java面试题精选

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

有一个用户线程存在,那么守护线程就不会结束,例如 java 中著名的垃圾回收器就是一个守护线程,只有应用程序中所有的线程结束,它才会结束。**

守护线程的特点:

一般守护线程是一个死循环,所有的用户线程只要结束,

守护线程自动结束。

示例代码(5):


/*

守护线程!!



### 最后

光给面试题不给答案不是我的风格。这里面的面试题也只是凤毛麟角,还有答案的话会极大的**增加文章的篇幅**,减少文章的可读性

# Java面试宝典2021版

[外链图片转存中...(img-6NQT5MWq-1715150524696)]

[外链图片转存中...(img-7Q0Snmay-1715150524696)]

# 最常见Java面试题解析(2021最新版)

[外链图片转存中...(img-fJTJSWN1-1715150524697)]

[外链图片转存中...(img-2OQO7eoV-1715150524697)]

# 2021企业Java面试题精选

[外链图片转存中...(img-VDEa2SOx-1715150524697)]

[外链图片转存中...(img-cd8LRG7x-1715150524698)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值