有关Thread的面试问题?
Posted 江西昊仔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有关Thread的面试问题?相关的知识,希望对你有一定的参考价值。
线程面试问题?
1.创建线程有几种方式?
常见的就两种:继承Thread类,实现Runnable接口;
还一种方式:JUC并发方向,实现Callable接口;
* 推荐: 避免单继承的局限性,优先使用接口
* 方便共享资源
* 方便共享资源
上面三种都是通过接口创建线程
最后这个:通过线程池来创建线程(稀少)
1.
继承Thread类
* 创建线程方式一:
* 1、创建:继承Thread+重写run
* 2、启动: 创建子类对象 + start
* 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
* 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 多种解决办法(代码片段