Java面试复习7 多线程

Java面试复习7 多线程

声明:本面试复习都基于一本未署名的Java面试宝典所述,根据自己的理解写出了这一专栏的复习博客

  1. 传统多线程实现方式

    继承Thread类创建线程

    1. 定义子类继承Thread类。
    2. 子类中重写Thread类中的run方法。
    3. 创建Thread子类对象,即创建了线程对象。
    4. 调用线程对象start方法:启动线程,调用run方法

    实现Runnable接口

    1. 定义子类,实现Runnable接口。
    2. 子类中重写Runnable接口中的run方法。
    3. 通过Thread类含参构造器创建线程对象。
    4. 将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。
    5. 调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。
    -----------------第一种写法--------------------实现Runnable接口
    public class MyThread2  implements Runnable{
    
    	@Override
    	public void run() {
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("Runable线程执行+++"+i);
    		}
    		
    	}
    
    }
    
    public class TestThread {
    	public static void main(String[] args) {
    		Thread t = new MyThread1();
    		t.start();//启动线程
    		
    		Runnable r = new MyThread2();
    		Thread t2 = new Thread(r);
    		t2.start();//启动第二个线程
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("主线程执行****************************************"+i);
    		}
    
    	}
    }
    
    -----------------第二种写法--------------------继承Thread创建
    public class MyThread1  extends Thread{
    	
    	@Override
    	public void run() {
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("自定义线程执行-----------------------"+i);
    		}
    	}
    }
    
    public class TestThread {
    	public static void main(String[] args) {
    		Thread t = new MyThread1();
    		t.start();//启动线程
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("主线程执行****************************************"+i);
    		}
    	}
    }
    
    
    -----------------第三种写法--------------------成员内部类
    public class TestThread {
    	public static void main(String[] args) {
    		Thread t1 = new TestThread().new  MyThread3();
    		t1.start();
    		Thread t2 = new Thread(new TestThread().new MyThread4());
    		t2.start();
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("主线程执行****************************************"+i);
    		}
    	//	t.start();
    	}
    	
    	class MyThread3 extends Thread {
    		@Override
    		public void run() {
    			for(int i = 0 ; i < 10000;i++) {
    				System.out.println("Thread线程执行-----------------------"+i);
    			}
    		}
    	}
    	class MyThread4 implements Runnable{
    
    		@Override
    		public void run() {
    			for(int i = 0 ; i < 10000;i++) {
    				System.out.println("Runable线程执行+++"+i);
    			}
    			
    		}
    		
    	}
    }
    
    -----------------第四种写法--------------------匿名内部类
    public class TestThread {
    	public static void main(String[] args) {
    		  new Thread() {
    			@Override
    			public void run() {
    				for(int i = 0 ; i < 10000;i++) {
    					System.out.println("Thread线程执行-----------------------"+i);
    				}
    			}
    		}.start();
    		
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				for(int i = 0 ; i < 10000;i++) {
    					System.out.println("Runable线程执行+++"+i);
    				}
    			}
    		}).start();
    		for(int i = 0 ; i < 10000;i++) {
    			System.out.println("主线程执行****************************************"+i);
    		}
    	}
    
    }
    
  2. 线程的生命周期

    新建(线程声明),
    就绪(Start()方法执行后,此时一切准备就绪,只需要获得CPU的资源就可以运行),
    运行(得到CPU后开始运行,失去后或者在线程得到让步(yield()方法)后又进入就绪状态),
    阻塞(正在运行的线程在遇到sleep(),wait(),suspend()方法或者join()方法或者等待同步锁后进入阻塞状态,当其获得同步锁,notify,notifyall,resume,或者sleep时间到又从阻塞状态变为就绪态,等待CPU的资源分配),
    死亡(stop或者遇到Erro/Exception,或者整个run执行完成后死亡)。

    Java面试复习7 多线程_第1张图片

    ---------------------------线程中的常用方法-------------------------
    
    
    void start(): 启动线程,并执行对象的run()方法 
    run(): 线程在被调度时执行的操作 
    String getName(): 返回线程的名称 
    void setName(String name):设置该线程名称 
    static Thread currentThread(): 返回当前线程。
                 在Thread子类中就 是this,通常用于主线程和Runnable实现类
    static void yield():线程让步 
        //暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程 
        //若队列中没有同优先级的线程,忽略此方法 
    join() :当某个程序执行流中调用其他线程的 join() 方法时,
    调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止 
        //低优先级的线程也可以获得执行 
    static void sleep(long millis)(指定时间:毫秒) 
        //令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,
        时间到后 重排队。 
        //抛出InterruptedException异常 
    stop(): 强制线程生命期结束,不推荐使用 
    boolean isAlive():返回boolean,判断线程是否还活着
    
  3. 程序,进程,线程的概念区别

    1. 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象
    2. 进程(process)程序的一次执行过程或是正在运行的一个程序是一个动态的过程:有它自身的产生、存在和消亡的过程。即生命周期
      如:运行中的QQ,运行中的MP3播放器
      程序是静态的,进程是动态的
      进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域
    3. 线程(thread)进程可进一步细化为线程,是一个程序内部的一条执行路径。
      一个进程同一时间并行执行多个线程,就是支持多线程
      线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
      一个进程中的多个线程共享相同的内存单元/内存地址空间—>它们从同一堆中分配对象,可以 访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资 源可能就会带来安全的隐患
  4. 简述线程的调度方式

    通常情况下是两种:
    时间片轮循(多个线程之间轮流循环进行),
    抢占式(高优先级的线程抢占CPU)

    同优先级线程组成先进先出队列(先到先服务),使用时间片策略
    对高优先级,使用优先调度的抢占式策略

    线程的优先级.

    MAX_PRIORITY:10
    MIN _PRIORITY:1
    NORM_PRIORITY:5 (通常情况下的优先级)
    涉及的方法
    getPriority() :返回线程优先值
    setPriority(int newPriority) :改变线程的优先级
    说明
    线程创建时继承父线程的优先级
    低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用

  5. 叙述线程的分类
    Java中的线程分为两类:一种是守护线程,一种是用户线程。

    它们在几乎每个方面都是相同的,唯一的区别是判断JVM何时离开。
    守护线程是用来服务用户线程的,通过在start()方法前调用 thread.setDaemon(true)可以把一个用户线程变成一个守护线程。
    Java垃圾回收就是一个典型的守护线程。
    若JVM中都是守护线程,当前JVM将退出。

  6. 线程的同步的方式

    借助synchronized关键字。加一把同步锁,来实现多线程的安全。

    同步代码块一个用synchronized声明的代码块

    同步方法一个用synchronized声明的方法

    上述两种都可以是静态的也可以是非静态的。

    同步代码块的锁对象

    当在非静态代码块中 对存在线程安全问题的代码实行同步策略 此时的锁对象可以是任意对象 只需要保证所有的线程使用的是同一个锁对象 this也可以充当锁对象

    静态代码块可以使用静态对象来作为锁对象 保证所有的线程使用的是同一个锁对象

    同步方法的锁对象?

    对于非静态方法 锁对象为this

    对于静态方法 字节码对象 本类的class对象

    synchronized (对象){ //这个对象可以使任意对象,但是被锁的代码需要保证是
    					//同一把锁,不能使用匿名对象
        // 需要被同步的代码; 
    }
    
    public synchronized void show (String name){}
    

    Java面试复习7 多线程_第2张图片Java面试复习7 多线程_第3张图片

  7. 线程的死锁

    出现原因:死锁的出现是因为锁的嵌套
    不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃 自己需要的同步资源,就形成了线程的死锁

    在开发中 应尽量避免死锁的出现 应尽量不要使用锁的嵌套,使用一些算法也可以避免死锁

    出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续

  8. 线程的通信

    其实就是方法的使用。这里只不过具体了那些方法的用途,切记wait和notify/notifyAll必须在同步代码中执行Java面试复习7 多线程_第4张图片

这里主要是对于线程一些基础知识的复习,线程部分的面试题都比较繁多,还未彻底看完, 后续会在这里继续进行更新。

更新ing…

你可能感兴趣的:(java面试与一些基础复习)