跳至主要內容

面试-多线程

TenSoFlow...大约 5 分钟面试面试-多线程

面试-多线程

谈谈线程和进程

问:谈谈线程和进程

答:进程是操作系统分配资源的最小独立单位,相当于一个独立运行的程序(比如打开的微信、IDEA),每个进程都有自己专属的内存空间,进程之间相互隔离、互不干扰。而线程是操作系统调度执行的最小单位,它不能独立存在,必须依附于进程,一个进程可以包含多个线程,这些线程共享所属进程的全部资源。

Java实现多线程的方式

问:Java实现多线程的方式

答:继承Thread类重写run()方法
实现Runnable接口重写run()方法
线程池(通过管理线程的方式)

package com.tensoflow;

class MyThread extends Thread {

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(200);
                System.out.println(Thread.currentThread().getName() + "执行中...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class ThreadCreateDemo {

    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        // 必须调用start(),不能直接调用run()(直接调是普通方法,不启动新线程)
        thread1.start();
        thread2.start();
    }

}

Thread类中的常用方法

问:Thread类中的常用方法

答:
start() 启动线程,并执行线程的run()方法
run() 线程的执行体
sleep() 让当前线程睡眠指定的毫秒数
setName() 设置线程名称
getName() 获取线程名称
setPriority(int priority) 设置线程的优先级
getPriority() 获取线程的优先级

如何让线程顺序执行

问:如何让线程顺序执行

答:使用join()方法把指定的线程加入到当前线程。

package com.tensoflow;

public class CccServiceApplication {
    
    public static void main(String[] args) throws Exception {
        
        Thread a = new Thread(() -> {
            for(int i = 0; i < 10000; i++) {
                System.out.println("aaa...");
            }
        });
        
        Thread b = new Thread(() -> {
            try {
                a.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i = 0; i < 10000; i++) {
                System.out.println("bbb...");
            }
        });
        
        b.start();
        a.start();
        System.out.println("主程序");
    }
    
}

wait()和sleep()有什么区别

问:wait()和sleep()有什么区别

答:从来源看:sleep() 来自Thread ,wait() 来自Object 。
从线程状态看:sleep() 导致当前线程进入timed_waiting状态,wait() 导致当前线程进入waiting状态。
从恢复执行看:sleep() 在指定时间之后,线程会恢复执行,wait() 则需要等待别的线程使用 notify()/notifyAll() 来唤醒它

守护线程是什么

问:守护线程是什么

答:守护线程是一种比较低级别的线程,一般用于为其他类别线程提供服务。因此当其它线程都退出时,它也就没有存在的必要了。例如JVM中的垃圾回收线程。主要应用有后台日志输出线程、后台监控线程(监控系统CPU、内存使用率、......)等。好处是仅在程序运行时需要,程序退出后自动终止无需手动关闭。

package com.tensoflow;

public class DaemonThreadDemo {
    
    public static void main(String[] args) {
        
        // 定义守护线程 b
        Thread b = new Thread(() -> {
            for (int i = 0; true; ++i) {
                try {
                    // 放慢打印速度,便于观察
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i + " " + Thread.currentThread().getName() + " is running.");
            }
        }, "Daemon-Thread");

        // 标记b为守护线程,必须写在start()方法之前
        b.setDaemon(true);
        // 启动线程
        b.start(); 

        // 主线程(用户线程)执行500ms后结束
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("主线程执行完毕,JVM 即将退出!");
        // 主线程结束后,守护线程b会被强制终止
    }
}

谈谈ThreadLocal

问:谈谈ThreadLocal

答:可以把ThreadLocal视为一个普通变量,其与普通的变量之间的区别在于ThreadLocal变量只属于某一个线程。单个ThreadLocal变量默认只存一个值。需要存多个值可以在ThreadLocal泛型中写上一个对象,使用对象存储多个值。其能解决线程内跨方法传递私有数据等问题。另外使用线程池时每次使用完都需要remove,不然会导致内存泄露与数据错乱。

package com.tensoflow;

class Person{
    String name = "zhangsan";
}

public class ThreadLocalTest {

    static ThreadLocal<Person> t1 = new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // null 即使第二个线程设置了new Person()
            System.out.println(t1.get());
        }).start();
        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            t1.set(new Person());
            // zhangsan 只有自己的线程能拿到这个Person对象
            System.out.println("线程二: " + t1.get().name);
        }).start();
    }
}

多线程怎么解决高并发

问:多线程怎么解决高并发

答:有两种。一种是Synchronized是利用锁的机制,使变量和代码块在某一时只能被一个线程访问。二是ThreadLocal其为每一个线程都提供变量的副本,使得每个线程在某一时间访问到的并不是同一对象,这样就隔离了多个线程对数据的数据共享。

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8