有关Thread的面试问题?

Posted 江西昊仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有关Thread的面试问题?相关的知识,希望对你有一定的参考价值。

线程面试问题?
 
1.创建线程有几种方式?
常见的就两种:继承Thread类实现Runnable接口
 
还一种方式:JUC并发方向,实现Callable接口
 
 * 推荐: 避免单继承的局限性,优先使用接口
 * 方便共享资源
 
上面三种都是通过接口创建线程
 
最后这个:通过线程池来创建线程(稀少)
 
1. 继承Thread类
 * 创建线程方式一:
 * 1、创建:继承Thread+重写run
 * 2、启动: 创建子类对象 + start
public class TestTheard {
    public static void main(String[] args) {
        Thread th = new Thread(new MyThread());
        th.start();

        Thread th2 = new Thread(new MyThread());
        th2.start();
        
        for(int i=0;i<10;i++) {
            System.out.print("憨憨就是你!!");
            if(i == 5){
                System.out.println();
            }
        }
    }
}


// 1.自定义多线程类
class MyThread extends Thread{
    @Override
    public void run() {
        for(int i=0 ; i<10 ; i++){
            System.out.print("我最帅!!"+i);
            if(i == 5){
                System.out.println();
            }
        }
    }
}

 
2.实现Runnable接口
 * 创建线程方式二:
 * 1、创建:实现Runnable+重写run
 * 2、启动: 创建实现类对象 +Thread对象+ start
 
public class TestRun {
    public static void main(String[] args) {
        //创建代理类对象
        Thread t =new Thread(new TestRunnable());
        //启动线程
        t.start();  //不保证立即运行 ,给cpu调度

        Thread t2 = new Thread(new TestRunnable());
        t2.start();

        for(int i=0;i<10;i++) {
            System.out.print("憨憨就是你!!");
            if(i == 5){
                System.out.println();
            }
        }
    }
}

class TestRunnable implements Runnable{

    @Override
    public void run() {
        for(int i=0 ; i<10 ; i++){
            System.out.print("我最帅!!"+i);
            if(i == 5){
                System.out.println();
            }
        }
    }
}

 
 
 
3 覆写Callable接口实现多线程
 
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口。)

(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。

(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值


//创建目标对象: CRacer racer = new CRacer();     
//创建执行服务: ExecutorService   ser=Executors.newFixedThreadPool(2); // 两个线程
//提交执行:  Future<Integer> result1 =ser.submit(racer) ;  Future<Integer> result2 =ser.submit(racer) ;
//获取结果:   Integer r1 =result1.get(); Integer r2  =result2.get();  // 我们只能获取他们里面的名字,不能自己给值
//关闭服务:  ser.shutdownNow();
/**
 * 
 */
package cn.lyh.Thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 用Callable: 模拟龟兔赛跑
	//创建目标对象: CRacer racer = new CRacer();	
	//创建执行服务: ExecutorService  ser=Executors.newFixedThreadPool(2); // 两个线程
	//提交执行:  Future<Integer> result1 =ser.submit(racer) ; Future<Integer> result2 =ser.submit(racer) ;
	//获取结果:   Integer r1 =result1.get(); Integer r2 =result2.get();  // 我们只能获取他们里面的名字,不能自己给值 
	//关闭服务:  ser.shutdownNow();
 *
 */
public class CRacer implements Callable<Integer>{
	private  String winner;//胜利者
	@Override
	public Integer call() throws Exception {
		for(int steps =1;steps<=100;steps++) {		
			//模拟休息
			if(Thread.currentThread().getName().equals("pool-1-thread-1") && steps%10==0) {
				Thread.sleep(100);
			}
			System.out.println(Thread.currentThread().getName()+"-->"+steps);
			//比赛是否结束
			boolean flag = gameOver(steps);
			if(flag) {
				return steps;
			}
		}
		return null;
	}
	private boolean gameOver(int steps) {
		if(winner!=null) { //存在胜利者
			return true;
		}else {
			if(steps ==100) {
				winner = Thread.currentThread().getName();
				System.out.println("winner==>"+winner);
				return true;
			}
		}
		return false;
	}
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		CRacer racer = new CRacer();
		//创建执行服务: 
		ExecutorService  ser=Executors.newFixedThreadPool(2);
		//提交执行: 
		Future<Integer> result1 =ser.submit(racer) ;
		Future<Integer> result2 =ser.submit(racer) ;
		//获取结果:  
		Integer r1 =result1.get();
		Integer r2 =result2.get();
		System.out.println(r1+"-->"+r2);
		//关闭服务:  
		ser.shutdownNow();
	}
}

 

 

1.并发,并行,串行的解释

并发:一个CPU执行多个任务,但会发生上下任务的切换(切换速度快),让我们看到的好像同时执行,但实际上不是同时执行,就好比一个老师多个学生问问题,老师先指点,让学生先想,然后接着指点下一位学生。
 
并行:多个CPU执行多个任务,这才是真正意义上的同时执行,就好比有多个老师多个学生问问题,每个老师可以同时间上指点不同的同学。
 
串行:按照顺序执行,好比一个老师需要解决完当前学生的问题,才解决下一位,学生们需要排一个队列,挨个询问。
 
 

2.什么是多线程,优缺点是什么

多线程:指代一个程序中含有多个执行流,运行程序可以让不同的线程执行不同的任务。
 
好处:可以提高CPU的利用率,因为加入一个线程进入了阻塞状态,CPU不会去等待,而是会进行执行其他的线程,让CPU忙起来,提高了效率
 
坏处:我们使用了多线程,需要考虑很多东西,比如说资源共享的一些问题
 
线程也是程序,需要占用内存
 
 

3.什么是线程和进程

功能进程操作系统资源分配的基本单位,而线程任务调度和执行的基本单位
 
 
开销: 每个进程都有独立的内存空间,存放代码和数据段等,程序之间的切换会有较大的开销;线程可以看做轻量级的进程,共享内存空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
 
 
运行环境: 在操作系统中能同时运行多个进程;而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
 
 
创建过程: 在创建新进程的时候,会将父进程的所有五大数据结构复制新的,形成自己新的内存空间数据,而在创建新线程的时候,则是引用进程的五大数据结构数据,但是线程会有自己的私有数据、栈空间。
 
 
 
 
模拟龟兔赛跑
class StudyThreadRacer implements Runnable {
    private static String winner;

    @Override
    public void run() {
        for (int steps = 1; steps <= 100; steps++) {
            System.out.println(Thread.currentThread().getName() + "--" + steps);
            // 比赛是否结束
            boolean flag = gameOver(steps);
            if (flag) {
                break;
            }
        }

    }

    private boolean gameOver(int steps) {
        if (winner != null) {
            return true;
        } else {
            if (steps == 100) {
                winner = Thread.currentThread().getName();
                System.out.println("winner==" + winner);
                return true;
            }
        }
        return false;
    }
}
public static void testTR(){
        StudyThreadRacer r = new StudyThreadRacer();
        new Thread( r , "tortoise" ).start();
        new Thread( r , "rabbit" ).start();
    }

 

以上是关于有关Thread的面试问题?的主要内容,如果未能解决你的问题,请参考以下文章

面试常用的代码片段

NDK: ant 错误 [javah] Exception in thread "main" java.lang.NullPointerException 多种解决办法(代码片段

vbscript 各种自定义代码片段 - 有关详细信息,请参阅注释

面向面试编程代码片段之GC

创作赢红包进线程有关的面试题

多线程 Thread 线程同步 synchronized