多线程
-
什么是线程?
线程是操作系统能够进行运算调度的最小单位;它被包含在进程之中,是进程中的实际运作单位。
-
线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,所有的线程共享一片相同的内存空间。
-
Java多线程的实现有哪些方法?
-
继承Thread类创建线程
Thread类本质上是实现了Runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。
例如:
public class MyThread extends Thread { public void run() { while(true) { System.out.println(this.getName()+" running..."); try { Thread.sleep(1000); // 休息1000ms } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[]args) { MyThread thread1 = new MyThread(); MyThread thread2 = new MyThread(); thread1.start(); thread2.start(); } } //执行结果 Thread-1 running... Thread-0 running... Thread-1 running... Thread-0 running... Thread-1 running... Thread-0 running... Thread-1 running... Thread-0 running... Thread-1 running... Thread-0 running... Thread-1 running... Thread-0 running...
-
实现Runnable接口
实现Runnable接口也是一种常见的创建线程的方式。使用接口的方式可以让我们的程序降低耦合度。Runnable接口中仅仅定义了一个方法,就是run。
其实Runnable就是一个线程任务,线程任务和线程的控制分离,这也就是上面所说的解耦。我们要实现一个线程,可以借助Thread类,Thread类要执行的任务就可以由实现了Runnable接口的类来处理。 这就是Runnable的精髓之所在!
例如:
//集成Runnable接口定义任务类 public class ThreadTask implements Runnable { @Override public void run() { while(true) { System.out.println(Thread.currentThread().getName()+" is running..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } //在main方法中创建线程去完成该任务 public class Main extends ThreadTask { public static void main(String[]args) { ThreadTask task = new ThreadTask();//新建任务类 Thread t1 = new Thread(task); t1.start(); Thread t2 = new Thread(task); t2.start(); } }
-
实现Callable接口
与实现Runnable接口实现多线程类似,也有不同
相同点:
两者都可用来编写多线程程序;
两者都需要调用Thread.start()启动线程;不同点:
两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;import java.util.concurrent.Callable; public class ThreadImplementsCallable implements Callable<Integer> { private int i; @Override public Integer call() throws Exception { for(; i < 100; i++){ System.out.println(Thread.currentThread().getName() + " " + i); } return i; } }
-
通过线程池来实现多线程
public class ThreadDemo05{ private static int POOL_NUM = 10; //线程池数量 /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub ExecutorService executorService = Executors.newFixedThreadPool(5); for(int i = 0; i<POOL_NUM; i++) { RunnableThread thread = new RunnableThread(); //Thread.sleep(1000); executorService.execute(thread); } //关闭线程池 executorService.shutdown(); } } class RunnableThread implements Runnable { @Override public void run() { System.out.println("通过线程池方式创建的线程:" + Thread.currentThread().getName() + " "); } } 执行结果 通过线程池方式创建的线程:pool-1-thread-3 通过线程池方式创建的线程:pool-1-thread-4 通过线程池方式创建的线程:pool-1-thread-1 通过线程池方式创建的线程:pool-1-thread-5 通过线程池方式创建的线程:pool-1-thread-2 通过线程池方式创建的线程:pool-1-thread-5 通过线程池方式创建的线程:pool-1-thread-1 通过线程池方式创建的线程:pool-1-thread-4 通过线程池方式创建的线程:pool-1-thread-3 通过线程池方式创建的线程:pool-1-thread-2
-
-
用Runnable还是Thread?
Java不支持类的多重继承,但允许调用多个接口。所以如果要继承其他类,当然是调用Runnable接口更好。
-
Thread类中的 start()和run()方法有什么区别?
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法会启动新线程。
-
volatile
volatile是一个特殊的修饰符,只有成员变量才能使用它。保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程来说是立即可见的。
-
线程的五大状态
新建状态:新建线程对象,并没有调用start()方法之前;
就绪状态:调用start()方法之后线程就进入就绪状态,但是并不是说只要调用start()方法线程就马上变为当前线程,在变为当前线程之前都是为就绪状态。值得一提的是,线程在睡眠和挂起中恢复的时候也会进入就绪状态;
运行状态:线程被设置为当前线程,开始执行run()方法。就是线程进入运行状态;
阻塞状态:线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态;
死亡状态:线程执行结束。
-
notify和notifyAll的区别
- 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
- 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只有一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。
- 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
-
多线程面试题集合
https://www.cnblogs.com/xiaowangbangzhu/p/10443289.html