对于Java多线程的常见问题

最近在准备工作面试的问题,所以找了很多的资料,和自己整理了相关可能会考到的。每天争取发一篇。

1.多线程

实现方法:

一、继承Thread,重写run方法,调用start即可。

Class Thread1 extends Thread{

Public void run(){

//添加代码

}

}

Public static void main(String[] args){

Thread1 st = new Thread1();

St.start();

}

二、实现runnable接口,重写run方法,调用start。

Class RunThrad implements runnable{

Public void run(){

//添加代码

}

}

RunThread t = new RunThread();

Thread th = new Thread(t);

th.start();

三、实现Callable接口类,并重写call方法,使用FutureTask类来包装Callable实现类的对象,并且使用FutureTask对象来作为Thread对象的target来创建线程。

class  Mycallable  implements  Callable<Integer>{

Public int call(){

//添加代码

}

}

public static void main(String[] args){

Mycallable<Integer> mycall = new Mycallable<Integer>();

FutureTask<Integer> ft = new FutureTask<Integer>(mycall);

Thread th = new Thread(ft);

th.start();

}

实现runnable和callable比继承Thread方法的优势:

1、避免单继承的问题。

2、线程池只能够放入runnable和callable类的线程。

线程主要有五种状态,如下:

接下来介绍sleep,wait,notify,notifyAll,join,yield六种方法

对于wait,notify,notifyAll这三个,属于object类的方法,但必须搭配synchronized同步块来使用,即在synchronized修饰的同步代码块中或者方法中调用wait或者notify/notifyAll:

由于wait,notify/notifyAll是放在同步代码块中的,所以线程在执行的时候,肯定是进入了临界状态的,即该线程肯定是获得了锁的。

当执行wait方法时,会把当前的锁释放掉,让出cpu,进入等待状态。

当执行notify/notifyAll方法时,唤醒一个等待该对象锁的线程,然后继续往下执行,直到执行完synchronized的代码后,再将锁释放。(注意,notify/notifyAll执行后,并不立即释放锁,而是需要等待执行完synchronized的代码后)

如果在线程A,线程B中,在线程A中,执行wait,在线程B中执行notify,如果线程B先执行了notify,然后就结束了,然后线程A才去执行wait,那么此时线程A就无法被唤醒了。举例如下:有3个线程A,B,C。

class T implements Runnable{

public String i;

public String index;

public T(String i,String index){

this.i = i;

this.index = index;

}

@Override

public void run() {

synchronized (index) {

while (true) {

try {

index.notifyAll();

System.out.println(i);

index.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

public class demo {

public static void main(String[] args){

String string1 = "s1";

String string2 = "s2";

String string3 = "s3";

String index = "test";

T a1 = new T(string1,index);

T a2 = new T(string2,index);

T a3 = new T(string3,index);

Thread thread1 = new Thread(a1);

Thread thread2 = new Thread(a2);

Thread thread3 = new Thread(a3);

thread1.start();

thread2.start();

thread3.start();

}

}

输出结果:

s2

s1

s3

s1

s2

s1

s3

s1

……

多线程中测试某个条件的变化用 if 还是用 while?

以前一直不明白 当在线程的run()方法中需要测试某个条件时,为什么用while,而不用if,直到看到了这个简单的例子,终于明白了。。。。

这个例子是这样的:

有两个线程从List中删除数据,而只有一个线程向List中添加数据。初始时,List为空,只有往List中添加了数据之后,才能删除List中的数据。添加数据的线程向List添加完数据后,调用notifyAll(),唤醒了两个删除线程,但是它只添加了一个数据,而现在有两个唤醒的删除线程,这时怎么办??

如果用 if 测试List中的数据的个数,则会出现IndexOutofBoundException,越界异常。原因是,List中只有一个数据,第一个删除线程把数据删除后,第二个线程再去执行删除操作时,删除失败,从而抛出 IndexOutofBoundException。

但是如果用while 测试List中数据的个数,则不会出现越界异常!!!神奇。

当wait等待的条件发生变化时,会造成程序的逻辑混乱---即,List中没有数据了,再还是有线程去执行删除数据的操作。因此,需要用while循环来判断条件的变化,而不是用if。

两个线程之间的通信,可以采用如下两种方式,一种是基于while轮询,另外一种就是wait/notify的方式。

基于while轮询的,B线程一直  一直循环条件,当符合条件时,则抛出异常,结束线程。

基于wait/notify的方式,则使用共享变量。当A线程放弃CPU使用权,进入阻塞状态,则B线程获得共享变量,开始执行,执行完毕后,B线程结束,放弃CPU使用权,A线程继续。容易出现的问题是,A线程尚未执行,B线程先执行,打乱执行顺序。则逻辑错误。

参考案例在:http://www.cnblogs.com/hapjin/p/5492619.html

sleep:

sleep让当前线程休眠指定的时间。休眠完成后,状态转到就绪状态。

yield:  yield是放弃当前CPU资源,将CPU资源让给其他线程去使用,但放弃的时间不确定。

join:

大部分情况下,主线程启动了子线程,如果子线程需要完成大量复杂的运算,则主线程会先于子线程结束。但主线程如果需要在子线程运行完毕后使用子线程的结果,则必须在主线程中使用join,这样主线程会等待子线程结束,然后主线程再结束。

方法join,是使得所属线程对象x正常执行完run方法,而使当前线程z进行无限制阻塞,直到对象x结束后,再继续执行z后面的代码。

public class demo

{

public static void main(String[] args) throws InterruptedException

{

Thread producer = new Producer();

producer.start();

producer.join();

System.out.println("main end");

}

}

class Producer extends Thread

{

public void run()

{

for (int i = 0; i < 100000; i++)

System.out.println("producer end");

}

}

在以上案例中,当把producer.join()注释掉后,会先打印main end,再打印producer end。因为子线程运算复杂,所以主线程会先结束。而如果加上这一句,则主线程会等待producer线程的结束,主线程再销毁。也就是说,哪一个线程被调用,则必须等待该线程结束,调用的主线程才能继续执行下一步。

时间: 2024-10-19 16:58:21

对于Java多线程的常见问题的相关文章

java多线程并发概览

一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在Windows系统中,一个运行的exe就是一个进程. 线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存. "同时"执行是人的感觉,在线程之间实际上轮换执行. 二.Java中的线程 在J

JAVA多线程和并发基础面试题

多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进程.线程可以被称为轻量级进程.线程需要较少的资源来创建和驻

汪大神Java多线程编程实战

课程目录:├─1│  ├─Java并发编程.png│  ├─源码+ppt.rar│  ├─高并发编程第一阶段01讲.课程大纲及主要内容介绍.wmv│  ├─高并发编程第一阶段02讲.简单介绍什么是线程.wmv│  ├─高并发编程第一阶段03讲.创建并启动线程.mp4│  ├─高并发编程第一阶段04讲.线程生命周期以及start方法源码剖析.mp4│  ├─高并发编程第一阶段05讲.采用多线程方式模拟银行排队叫号.mp4│  ├─高并发编程第一阶段06讲.用Runnable接口将线程的逻辑执行单元

最常见的15个Java多线程,并发面试问题

例如,用于DMA交易的高容量和低延迟电子交易系统通常是并发的.大多数情况下,他们专注于微秒延迟,这就是为什么拥有如何有效地最小化延迟和提高吞吐量知识是如此重要. 这些是我最喜欢的关于Java的线程面试问题.我没有提供这些线程访谈问题的答案,但我会尽可能给你一个提示.我会更新帖子就详细的答案,就像我最近在Java中发布的10个Singleton面试问题一样. 15 Java Thread Interview Questions and answers 无论如何,这里是一些常见的Java多线程和并发

Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3534050.html Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可

从JAVA多线程理解到集群分布式和网络设计的浅析

对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些常用的,在后续文章中如果有必要再说明更加复杂的吧,本文主要说明多线程的一下几个内容: 1.在应用开发中什么时候选择多线程? 2.多线程应该注意些什么? 3.状态转换控制,如何解决死锁? 4.如何设计一个具有可扩展性的多线程处理器? 5.多线程联想:在多主机下的扩展-集群? 6.WEB应用的多线程以及

java多线程心得

多并发的时候,在什么情况下必须加锁?如果不加锁会产生什么样的后果. 加锁的场景跟java的new thread和Runnable的关系是什么? 看看java的concurrentMap源码. 还有spring 的web.xml启动执行源码 spring aop http://www.cnblogs.com/FDROSE1001/p/3661895.html activemq的本质是什么? java的jms hibernate由配置文件映射到实体类的本质是什么? java反射 spring aop

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

(转载)Java多线程入门理解

转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalan