Java多线程的基本知识

9个月前 (11-28) wang JAVA, 技术杂谈 0评论 已收录 89℃ 浏览数:67

假设如下代码中,若t1线程在t2线程启动之前已经完成启动。代码的输出是()

	public static void main(String[] args) throws Exception {
		final Object obj = new Object();
		Thread t1 = new Thread() {
			public void run() {
				synchronized (obj) {
					try {
						obj.wait();
						System.out.println("Thread 1 wake up.");
					} catch (InterruptedException e) {
					}
				}
			}
		};
		
		t1.start();
		Thread.sleep(1000);// We assume thread 1 must start up within 1 sec.
		Thread t2 = new Thread() {
			public void run() {
				synchronized (obj) {
					obj.notifyAll();
					System.out.println("Thread 2 sent notify.");
				}
			}
		};
		t2.start();
	}

  • Thread 1 wake up
    Thread 2 sent notify.
  • Thread 2 sent notify.
    Thread 1 wake up
  • A、B皆有可能
  • 程序无输出卡死

输出的结果是

  • Thread 2 sent notify. Thread 1 wake up

原因是wait就是说线程在获取对象锁后,进入阻塞状态,主动释放对象锁,同时本线程休眠。需要等待其他进程进行唤醒。notifyAll方法是线程2获得了对象锁,这时线程2没有释放锁,所以线程1没有办法运行。只有等线程2执行结束,释放了对象锁,唤醒线程1,线程1获得了对象锁,进入就绪状态 ,等待处理机调用,然后开始运行。

 

1.线程间协作:wait、notify、notifyAll

在Java中,可以通过配合调用Objet对象的wait,notify和notifyAll方法来实现进程间的通信。在线程中调用wait方法,该线程被阻塞,等待其他线程调用notify或者notify方法进行通知。在线程中调用notify或者notifyAll方法,将通知其他线程从wait方法返回,

Object是所有类的超类,五个方法组成了等待通知机制的核心。notify,notifyAll,wait,wait long,wait long,wait。所有的类都是继承Object类,所有的类都拥有这些方法,这些方法被声明为final,因此子类中无法覆写任何一个方法。

wait

public final void wait() throws InterruptedException,IllegalMonitorStateException

方法必须在同步方法或者同步块里面进行调用,在调用前,需要获得该对象的对象级别锁。如果在调用wait方法时没有获得锁,则会抛出IllegalMonitorStateException异常,是RuntimeException的之类。

在进入wait方法后,当前线程释放锁,进入阻塞状态,在从wait方法返回之前,线程会与其他线程竞争重新获得锁,

notify

public final native void notify() throws IllegalMonitorStateException

方法必须在同步方法或者同步块里面进行调用,在调用前,需要获得该对象的对象级别锁。如果在调用notify方法时没有获得锁,则会抛出IllegalMonitorStateException异常,是RuntimeException的之类。

该方法用来通知那些等待唤醒的线程。如果有多个线程等待唤醒,则从线程规划器中(我认为是栈)选取一个线程进行唤醒,当前线程也不会马上释放该对象锁,需要等待当前的同步代码块执行完毕,当前线程释放锁,其他线程才能获得锁,才能从wait方法进行返回,其他线程继续阻塞,等待其他的线程发出notify或者notifyAll。他们等待的是notify或者notifyAll,而不是锁。一个线程被唤醒,才会等待锁,获得锁才可以继续执行。

notifyAll

public final native void notifyAll() throws IllegalMonitorStateException

notifyAll使所有的原来在wait的线程全部退出wait状态,全部被唤醒,但是还没有获得锁,所以不能继续执行。变成等待获取该对象上的锁,一旦该对象锁被释放,他们就会去竞争。一个对象获得锁后就回去继续执行,直到他退出synchronized代码块,其他已经被唤醒的线程会继续竞争该锁,然后直到都有的线程都执行完毕。

深入理解

如果线程调用了该对象的wait方法,那么线程进入该对象等待池,等待池中的线程不会去竞争该对象的锁。

当有线程调用了线程的notifyAll方法,或者notify方法,被唤醒的线程变进入该对象的锁池中,锁池中的资源会去竞争该对象锁。获取到的对象执行,如果没有获取到,则继续留在锁池,线程继续调用wait方法后,才会会到等待池。竞争到对象锁的线程继续执行,执行完了synchronized代码块,释放对象锁,其他锁池的线程会继续竞争。

 

2.Java前后台线程

main()函数即主函数,是一个前台线程,前台进程是程序中必须执行完成的,而后台线程则是java中所有前台结束后结束,不管有没有完成。后台线程主要用与内存分配等方面。
前台线程和后台线程的区别和联系:

1、后台线程不会阻止进程的终止。属于某个进程的所有前台线程都终止后,该进程就会被终止。所有剩余的后台线程都会停止且不会完成。

2、不管是前台线程还是后台线程,如果线程内出现了异常,都会导致进程的终止。

3、托管线程池中的线程都是后台线程,使用new Thread方式创建的线程默认都是前台线程。

说明:

应用程序的主线程以及使用Thread构造的线程都默认为前台线程
使用Thread建立的线程默认情况下是前台线程,在进程中,只要有一个前台线程未退出,进程就不会终止。主线程就是一个前台线程。而后台线程不管线程是否结束,只要所有的前台线程都退出(包括正常退出和异常退出)后,进程就会自动终止。一般后台线程用于处理时间较短的任务,如在一个Web服务器中可以利用后台线程来处理客户端发过来的请求信息。而前台线程一般用于处理需要长时间等待的任务,如在Web服务器中的监听客户端请求的程序,或是定时对某些系统资源进行扫描的程序。

jre 判断程序是否执行结束的标准是 所有的前台线程执行完毕

3.线程五种状态

在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。

实现并启动线程有两种方法
1、写一个类继承自Thread类,重写run方法。用start方法启动线程
2、写一个类实现Runnable接口,实现run方法。用new Thread(Runnable target).start()方法来启动

调用start()后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可动行状态。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体。先调用start后调用run,这么麻烦,为了不直接调用run?就是为了实现多线程的优点,没这个start不行。
1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
记住:多线程就是分时利用CPU,宏观上让所有线程一起执行 ,也叫并发
博主

Just do it. Now or never.

相关推荐

嗨、骚年、快来消灭0回复。