`
george.gu
  • 浏览: 73550 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java Threads

 
阅读更多

Some Concepts in Thread Control

Here I would like to list some concepts I used to be not aware of.

Daemon Threads

Daemon threads are service providers for other threads running in the same process as the daemon thread. The run() method for a daemon thread is typically an infinite loop that waits for a service request.

 

When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.

 

Any Java thread can be a daemon thread. To specify that a thread is a daemon thread, call the setDaemon method with the argument true. To determine if a thread is a daemon thread, use the accessor method isDaemon.

Thread Priority

When a Java thread is created, it inherits its priority from the thread that created it. You can also modify a thread's priority at any time after its creation using the setPriority method. Thread priorities are integers ranging between MIN_PRIORITY and MAX_PRIORITY (constants defined in the Thread class). The higher the integer, the higher the priority.

 

At any given time, when multiple threads are ready to be executed, the runtime system chooses the runnable thread with the highest priority for execution. Only when that thread stops, yields, or becomes not runnable for some reason will a lower priority thread start executing. If two threads of the same priority are waiting for the CPU, the scheduler chooses one of them to run in a round-robin fashion. The chosen thread will run until one of the following conditions is true:

  • A higher priority thread becomes runnable.
  • It yields, or its run method exits.
  • On systems that support time-slicing, its time allotment has expired.

Then the second thread is given a chance to run, and so on, until the interpreter exits.

Selfish Threads

In some Threads, there could be a while(true) condition block to execute some behavior infiity.  For example:

 

public int token = 1;
public void run() {
    while (token < n) {
        token++;
    }
} 

 

The while loop in the run method is in a tight loop. Once the scheduler chooses a thread with this thread body for execution, the thread never voluntarily relinquishes control of the CPU--the thread continues to run until the while loop terminates naturally or until the thread is preempted by a higher priority thread. This thread is called a selfish thread.

 

In some situations, having selfish threads doesn't cause any problems because a higher priority thread preempts the selfish one (just as the drawing thread in the RaceApplet preempts the selfish runners). However, in other situations, threads with CPU-greedy run methods, such as the Runner class, can take over the CPU and cause other threads to wait for a long time before getting a chance to run.

Time-Slicing

Time-slicing comes into play when there are multiple "Runnable" threads of equal priority and those threads are the highest priority threads competing for the CPU.

 

The Java runtime does not implement (and therefore does not guarantee) time-slicing. However, some systems on which you can run Java do support time-slicing. Your Java programs should not rely on time-slicing as it may produce different results on different systems.

Summary

  • Most computers have only one CPU, so threads must share the CPU with other threads. The execution of multiple threads on a single CPU, in some order, is called scheduling. The Java runtime supports a very simple, deterministic scheduling algorithm known as fixed priority scheduling.

  • Each Java thread is given a numeric priority between MIN_PRIORITY and MAX_PRIORITY (constants defined in the Thread class). At any given time, when multiple threads are ready to be executed, the thread with the highest priority is chosen for execution. Only when that thread stops, or is suspended for some reason, will a lower priority thread start executing.

  • Scheduling of the CPU is fully preemptive. If a thread with a higher priority than the currently executing thread needs to execute, the higher priority thread is immediately scheduled.
  • The Java runtime will not preempt the currently running thread for another thread of the same priority. In other words, the Java runtime does not time-slice. However, the system implementation of threads underlying the Java Thread class may support time-slicing. Do not write code that relies on time-slicing.

  • In addition, a given thread may, at any time, give up its right to execute by calling the yield method. Threads can only yield the CPU to other threads of the same priority--attempts to yield to a lower priority thread are ignored.

  • When all the runnable threads in the system have the same priority, the scheduler chooses the next thread to run in a simple, non-preemptive, round-robin scheduling order.

Thread Group

The runtime system puts a thread into a thread group during thread construction. When you create a thread, you can either allow the runtime system to put the new thread in some reasonable default group or you can explicitly set the new thread's group.

The thread is a permanent member of whatever thread group it joins upon its creation--you cannot move a thread to a new group after the thread has been created.

Synchronized Threads Programming 

Monitors

In order to run a Object's method, Thread should acquire the monitor of this object.

 

A monitor is associated with a specific data item (a condition variable) and functions as a lock on that data. When a thread holds the monitor for some data item, other threads are locked out and cannot inspect or modify the data.

The code segments within a program that access the same data from within separate, concurrent threads are known as critical sections. In the Java language, you mark critical sections in your program with the synchronized keyword.


wait() , notify() and notifyAll()

Both notifyAll and wait are members of the java.lang.Object class. The notifyAll and wait methods can be invoked only by the thread that holds the lock.

 

We use wait in conjunction with notify or notifyAll to coordinate the activities of multiple threads using the same resources.

When the thread enters the wait method, the monitor is released atomically, and when the thread exits the wait method, the monitor is acquired again. This gives the waiting object the opportunity to acquire the monitor and, depending on who's waiting, resume the pending operations again.

Difference between notifyAll() and notify()

notifyAll() wakes up the thread that is waiting to get the object's monitor. 

 

notify() arbitrarily wakes up one of the threads waiting on the monitor. In this situation, each of the remaining waiting threads continues to wait until the monitor is relinquished and it is chosen by the runtime system. The use of notify can be ill-conditioned, that is, it can fail when the conditions are changed just a little. Solutions based on notifyAll tend to be more robust. A programmer who is not going to analyze a multi-threaded program sufficiently carefully is better off using notifyAll().

 

Difference between wait and sleep

Besides using these timed wait methods to synchronize threads, you can also use them in place of sleep. Both methods delay for the requested amount of time, but you can easily wake up wait with a notify. The thread can then see immediately that it should go away. This doesn't matter too much for threads that don't sleep for long, but it could be important for threads that sleep for minutes at a time.

Demo on sychronized threads programming

I put the java source code demo to help memory recovery in future.

Resource.java:

 

/**
 * @author wgu
 * 
 */
public class Resource {
	private int content = 0;
	private boolean signal = false;

	public synchronized int get() {
		while (!signal) {
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		signal = false;
		notifyAll();
		return content;
	}

	public synchronized void put(int i) {
		while (signal) {
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		signal = true;
		content = i;
		notifyAll();
	}
}

 

 Producer.java:

 

public class Producer extends Thread {
	int times;
	int id;
	Resource data;

	public Producer(Resource data, int times) {
		this(0, data, times);
	}

	public Producer(int id, Resource data, int times) {
		this.times = times;
		this.data = data;
		this.id = id;
	}

	public void run() {
		for (int i = 0; i < times; i++) {
			System.out.println("Producer #" + id + " put: " + i);
			data.put(i);

			try {
				// to make sure the output displayed sequentely
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
	}
}

 

 Consumer.java:

 

/**
 * @author wgu
 * 
 */
public class Consumer extends Thread {
	int times;
	int id;
	Resource data;

	public Consumer(Resource data, int num) {
		this(0, data, num);
	}

	public Consumer(int id, Resource data, int num) {
		this.times = num;
		this.data = data;
		this.id = id;
	}

	public void run() {
		for (int i = 0; i < times; i++) {
			System.out.println("Consumer #" + id + " get: " + data.get());
		}
	}
}

 

 Test application, Main.java:

 

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Resource data = new Resource();
		Producer p0 = new Producer(data, 10);
		Consumer c0 = new Consumer(data, 10);

		Resource data1 = new Resource();
		Producer p1 = new Producer(1, data1, 10);
		Consumer c1 = new Consumer(1, data1, 10);

		p0.start();
		c0.start();

		p1.start();
		c1.start();
	}

}

//The output will be. Order could be different in different machine.

Producer #0 put: 0
Consumer #0 get: 0
Producer #1 put: 0
Consumer #1 get: 0
Producer #1 put: 1
Consumer #1 get: 1
Producer #0 put: 1
Consumer #0 get: 1
Producer #0 put: 2
Consumer #0 get: 2
Producer #1 put: 2
Consumer #1 get: 2
Producer #0 put: 3
Consumer #0 get: 3
Producer #1 put: 3
Consumer #1 get: 3
Producer #0 put: 4
Consumer #0 get: 4
Producer #1 put: 4
Consumer #1 get: 4
Producer #0 put: 5
Producer #1 put: 5
Consumer #0 get: 5
Consumer #1 get: 5
Producer #1 put: 6
Producer #0 put: 6
Consumer #1 get: 6
Consumer #0 get: 6
Producer #0 put: 7
Producer #1 put: 7
Consumer #1 get: 7
Consumer #0 get: 7
Producer #0 put: 8
Producer #1 put: 8
Consumer #0 get: 8
Consumer #1 get: 8
Producer #1 put: 9
Consumer #1 get: 9
Producer #0 put: 9
Consumer #0 get: 9

 

Avoid no-synchronization implementation

During synchronization implementation, we could meet the problem there is no synchronization. It could happen in many cases:

 

  • "synchronized " key word is not declared for resource's methods.
For example:
public /*synchronized*/ int get() {
		while (!signal) {
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		signal = false;
		notifyAll();
		return content;
	}

public /*synchronized*/ void put(int i) {
		while (signal) {
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		signal = true;
		content = i;
		notifyAll();
	}
 There will be IllegalMonitorStateException raised:
Producer #0 put: 0
Exception in thread "Thread-0" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.notifyAll(Native Method)
	at com.gemalto.wgu.threads.test.Resource.put(Resource.java:29)
	at com.gemalto.wgu.threads.test.Producer.run(Producer.java:23)
java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Unknown Source)
	at com.gemalto.wgu.threads.test.Resource.get(Resource.java:11)
	at com.gemalto.wgu.threads.test.Consumer.run(Consumer.java:22)
  • Or Object in synchronized(Object) block is not common for multiple Threads

To avoid a no-synchronization scenario, choose an object common to all relevant threads. That way, those threads compete to acquire the same object's lock, and only one thread at a time can enter the associated critical code section.

 

join()

I list here the java source code from java.lang.Thread.join(int):

 

	/**
	 * Waits at most <code>millis</code> milliseconds for this thread to die. A
	 * timeout of <code>0</code> means to wait forever.
	 * 
	 * @param millis
	 *            the time to wait in milliseconds.
	 * @exception InterruptedException
	 *                if any thread has interrupted the current thread. The
	 *                <i>interrupted status</i> of the current thread is cleared
	 *                when this exception is thrown.
	 */
	public final synchronized void join(long millis)
			throws InterruptedException {
		long base = System.currentTimeMillis();
		long now = 0;

		if (millis < 0) {
			throw new IllegalArgumentException("timeout value is negative");
		}

		if (millis == 0) {
			while (isAlive()) {
				wait(0);
			}
		} else {
			while (isAlive()) {
				long delay = millis - now;
				if (delay <= 0) {
					break;
				}
				wait(delay);
				now = System.currentTimeMillis() - base;
			}
		}
	}
 

Deadlock

JVM cannot detect or prevent deadlock. 

 

During multiple synchronized threads programming, we should provent "deadlock". For example, Both ThreadA and ThreadB needs monitros of resource1 and resource2, in case ThreadA acquire monitor of resource1 and ThreadB acquires monitor of resource2 in same time, they will be queued to waiting for the monitor release of the other.  


In order to prevent "Deadlock" issue, you have to carefully analyze source code to avoid the situations where threads might attempt to acquire each others' locks.
Here list some known programming error which could lead to deadlock:
  1. When a synchronized method calls another synchronized method.
  2. Threads cycle acquire each's resources.

Usage in My Projects

ThreadPoolExecutor from JDK 1.5

  1. ScheduledThreadPoolExecutor to launch some scheduled tasks in system level.
  2. ThreadPoolExecutor to execute some business works.

Multiple processor in Server/Request architecture

Multiple processor in socketserver side to process multiple socket client. 

This implementation comes before JDK1.5. From JDK1.5, we can use ThreadPoolExecutor to execute tasks which will process client requests.

 

Monitor Resources Status by using wait() and notifyAll()

Object.wait() and Object.notifyAll() to monitor Driver Status in DriverManager. Only after making sure all Drivers are shutdown properly, DriverManager could be cleaned.

 

 

分享到:
评论

相关推荐

    Java Threads Third Edition.chm

    Java Threads Third Edition.chm

    java Threads

    Java线程是多任务编程的核心概念,特别是在Java这种支持并发执行的语言中。本文将深入探讨Java线程的创建、管理以及相关同步机制,基于提供的压缩包文件中的章节名称,我们可以推测这些章节可能涵盖线程的基本概念到...

    Java Threads 2rd

    ### Java Threads 2rd #### 书名:Java Threads 2rd 本书由Scott Oaks与Henry Wong合著,是关于Java线程技术的权威指南。它深入探讨了Java中的线程概念、API以及如何在多处理器环境中高效地利用线程进行编程。 ##...

    Java Threads Third Edition

    《Java Threads Third Edition》是Java多线程编程领域的一本经典著作,全面深入地探讨了Java平台上的线程管理和同步技术。这本书详细对比了JDK 1.4和JDK 1.5之间的差异,帮助开发者理解不同版本下线程处理的进化与...

    Java Threads and the Concurrency Utilities

    《Java多线程与并发工具》一书深入讲解了Java中线程API和并发工具的使用,这些内容是Java语言中最强大但也最具挑战性的API和语言特性之一。对于初学者而言,利用这些特性编写正确的多线程应用程序通常是非常困难的。...

    Java Threads英文第三版

    根据提供的文件信息,这是一本名为《Java Threads英文第三版》的技术书籍,专注于Java多线程编程。内容涵盖了从线程的基本概念到复杂的线程同步技术。以下是对标题和描述中提到知识点的详细说明。 ### 知识点说明 ...

    Java.Threads.3rd.Edition.txt

    根据提供的文件信息,我们可以推断出这是一本关于Java线程技术的书籍——《Java Threads 第三版》。下面将从书中的各个章节提取并总结关键知识点。 ### 一、绪论 #### 5.31.3 为什么需要线程? 在现代编程中,...

    Java Threads and the Concurrency Utilities 无水印pdf

    Java Threads and the Concurrency Utilities 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权...

    show-busy-java-threads.sh文件

    `show-busy-java-threads.sh`脚本就是为了帮助开发者快速定位和排查这类性能问题而设计的。这个脚本主要用于监控并展示Java应用程序中的繁忙线程,从而帮助我们理解程序的执行状态,找出可能导致高CPU负载的原因。 ...

    linux实用脚本show-busy-java-threads

    本文将深入探讨标题所提及的三个实用脚本:“show-busy-java-threads”、“show-duplicate-java-classes”以及“find-in-jars”。这些脚本都是针对Java开发者和系统管理员的利器,旨在提高效率和解决问题。 1. **...

    Java Threads, 3rd Edition, Scott Oaks and Henry Wong

    Java Threads, Third Edition, has been thoroughly expanded and revised. It incorporates the con-currency utilities from java.util.concurrent throughout. New chapters cover thread performance, using ...

    Concurrent, Real-Time and Distributed Programming in Java Threads, RTSJ 无水印原版pdf

    Concurrent, Real-Time and Distributed Programming in Java Threads, RTSJ and RMI 英文无水印原版pdf pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本资源转载自网络...

    APress-Taming-Java-Threads-Code.rar_taming java threads_threads

    《驯服Java线程》是Apress出版的一本关于Java多线程编程的书籍,它深入探讨了如何在Java环境中有效地管理和控制线程,以优化程序性能和稳定性。线程在现代软件开发中扮演着至关重要的角色,尤其是在并发处理和高并发...

    Java Threads and the Concurrency Utilities(Apress,2015)

    Threads and the Concurrency Utilities helps all Java developers master and use these capabilities effectively. This book is divided into two parts of four chapters each. Part 1 focuses on the Thread...

    Introduction to Java Threads

    ### Java线程介绍 #### 关于本教程 本教程旨在为Java程序员提供关于线程的基础知识,包括线程的概念、用途以及如何编写简单的多线程程序。此外,本教程还会探讨更复杂的线程应用程序的基本构建模块,如在不同线程...

Global site tag (gtag.js) - Google Analytics