1. 创建线程
Java的线程继承自Thread的类,处理一个名为run的方法。
class MyThread extends Thread {
private int i = 0;
public void run() {
while (true) {
System.out.println(++i);
if (i > 100) break;
}
}
}

public class program {
public static void main(String[] args){
new MyThread().start();
}
}
而对于那些不能继承 Thread 的类,可以采取实现 Runnable 接口的方式进行。
2. 执行权转交
对于暂时交出执行权,Java 提供了 Thread.yield() 方法.
class MyThread extends Thread {
public void run() {
int i = 0;
while (true) {
System.out.println( getName()+"-----------"+(++i));
if (i > 100) break;
yield();
}
}
}

public class ThreadTest {
public static void main(String[] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
结果:
t1-----------1
t2-----------1
t1-----------2
t2-----------2
t1-----------3
t2-----------3
t1-----------4
t2-----------4
t1-----------5
t2-----------5
.....
Java 也提供了 Thread.sleep(); 方法,但由于 Thread.sleep 可能被 interrupt( ) 方法中断,因此必须包含在 try{} 代码块中。
class MyThread extends Thread {
public void run() {
int i = 0;
while (true) {
System.out.printf("%s=%d\n", getName(), ++i);
if (i > 100) break;
try
{
sleep(0);
}
catch (InterruptedException e)
{
}
}
}
}

public class program {
public static void main(String[] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
3. 优先级
Java 使用 setPriority( ) 方法调整优先级。
4. 背景线程
Java 使用 setDaemon() 方法。在 Java 中一般将背景线程称之为"守护线程(daemon thread)"。需要注意的是即便背景线程未结束,进程依然会终止。必须在线程启动前设置。
5. 线程等待
Java 中都使用 join/Join() 方法阻止调用线程,直到某个线程结束。不过 Java 里面情况还是要复杂一些。当某个线程处于 join 等待时,它可能会被 interrupt( ) 方法中断,因此也得放在 try{} 代码块中。
package tread;

class ThreadT extends Thread {
public boolean stopFlag = false;

public void run() {
int i = 0;
while (!stopFlag) {
System.out.println(++i);
yield();
}

System.out.println("MyThread over");
}
}

class JoinThread extends Thread {
public void run() {
ThreadT my = new ThreadT();
my.start();

try {
my.join();
} catch (InterruptedException e) {
my.stopFlag = true;
System.out.println("JoinThread InterruptedException");
}
}
}

public class JoinTest {
public static void main(String[] args) {
JoinThread join = new JoinThread();
join.start();
try {
join.sleep(100*5);
join.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
。。。。。。
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
JoinThread InterruptedException
MyThread over
6. 资源锁定
Java 提供了 synchronized 关键字用来解决多线程资源共享锁定的问题,synchronized 可用于方法或者某个代码段。
package tread;

class Res {
String lock="";
synchronized static void test() {
for (int i = 0; i < 10; i++) {
System.out.println( Thread.currentThread().getName()+"========="+ i);
Thread.yield();
}
}

void test2() {
synchronized(lock){
for (int i = 0; i < 10; i++) {
System.out.println( Thread.currentThread().getName()+"========"+ i);
Thread.yield(); //没有放弃锁
}
}
}
}

class MyThreadA extends Thread {
public void run() {
new Res().test2();
}
}

public class SynTest {
public static void main(String[] args){
MyThreadA t1 = new MyThreadA();
MyThreadA t2 = new MyThreadA();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
当我们取消 synchronized 关键字时,我们会发现 t1 和 t2 交替执行。添加 synchronized 关键字以后,t2 会在 t1 执行完成后执行,因此对于方法的锁定是成功的。
结果:
t1========0
。。。。
t1========7
t1========8
t1========9
t2========0
。。。
t2========8
t2========9
另外,需要注意的是 synchronized 是全局锁定,也就是说对于静态方法而言,它们会锁定全部有此标记的方法(尽管它们不是同一个方法);而对于对象实例,它们会锁定同一对象全部有此标记的方法(尽管它们不是同一个方法)。
7. 原子操作
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行倒结束,中间不会有任何线程切换操作。
通常所说的Java原子操作包括对非long和double型的primitive进行赋值,以及返回这两者之外的primitive。之所以要把它们排除在外是因为它们都比较大,而JVM的设计规范又没有要求读操作和赋值操作必须是原子操作(JVM可以试着去这么作,但并不保证)。不过如果你在long或double前面加了volatile,那么它就肯定是原子操作了。
看下面的例子,虽然 return i是一个原子操作,但是从获得i的值到方法返回之间有可能被其他线程修改,因此不要主观的认为下面的操作是原子操作。我们还是有必要为其添加同步关键字synchronized。另外 ++i 和 --i 都不是原子操作,它们都涉及读和写两个步骤。
《Thinking in Java》中关于最安全的做法提出了如下的方针,不过我不完全赞同。
8. 线程协同
Java用对象锁来控制多线程安全,而所谓多线程协同无非是利用某种锁机制让线程暂时停顿下来,直到某个“信号”发生。为此,Java 将用来进行多线程协同的方法放在了根 Object 上,包括 wait(); notify(); notifyAll(); 。
调用 wait() / notify() / notifyAll() 之前必须先获取其对象锁,否则会抛出"IllegalMonitorStateException - current thread not owner" 异常。
package tread;

class MyThread extends Thread {

static Object o = new Object();

public void run() {
synchronized (o) {
int i = 0;
while (++i < 10) {
System.out.println(i);
try
{
if (i == 5) o.wait();
}
catch (InterruptedException e)
{
}
}
}
}
}

public class SynTest2 {

public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
while (t1.getState() != Thread.State.WAITING)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
}
}

System.out.println("Notify Thread
");
synchronized(MyThread.o)
{
MyThread.o.notify();
}
}
}
输出
1
2
3
4
5
Notify Thread...
6
7
8
9
在上面这个例子中,当 i 等于 5 时,我们调用了对象锁 o 的 wait 方法阻塞线程。在 main 方法中我们循环检查对象状态,并适时发出信号结束等待。这个例子虽然很简单,但是由此可以处理多个线程之间的协同关系。当然,我们还可以给 wait 方法加一个参数,让其等待特定的时间,而不是上面例子中的无限制等待。
需要注意的是 wait() 会释放对象锁,sleep() 则不会。接着看下面的例子。
输出
t1 - 1
t1 - 2
t1 - 3
t1 - 4
t1 - 5
t2 - 1
t2 - 2
t2 - 3
t2 - 4
t2 - 5
9. 停止/中断线程
线程退出最好自己实现,在运行状态中一直检验一个状态,如果这个状态为真,就一直运行,如果外界更改了这个状态变量,那么线程就停止运行。
Java 不推荐使用 stop() / about() / suspend() / resume() 之类的方法来停止线程。原因包括:
当线程因某种原因处于阻塞等待状态时,我们就无法使用旗标终止它,那么改用interrupt()好了。
Java的线程继承自Thread的类,处理一个名为run的方法。















而对于那些不能继承 Thread 的类,可以采取实现 Runnable 接口的方式进行。
2. 执行权转交
对于暂时交出执行权,Java 提供了 Thread.yield() 方法.























结果:











Java 也提供了 Thread.sleep(); 方法,但由于 Thread.sleep 可能被 interrupt( ) 方法中断,因此必须包含在 try{} 代码块中。






























3. 优先级
Java 使用 setPriority( ) 方法调整优先级。
4. 背景线程
Java 使用 setDaemon() 方法。在 Java 中一般将背景线程称之为"守护线程(daemon thread)"。需要注意的是即便背景线程未结束,进程依然会终止。必须在线程启动前设置。
5. 线程等待
Java 中都使用 join/Join() 方法阻止调用线程,直到某个线程结束。不过 Java 里面情况还是要复杂一些。当某个线程处于 join 等待时,它可能会被 interrupt( ) 方法中断,因此也得放在 try{} 代码块中。















































结果:













6. 资源锁定
Java 提供了 synchronized 关键字用来解决多线程资源共享锁定的问题,synchronized 可用于方法或者某个代码段。









































当我们取消 synchronized 关键字时,我们会发现 t1 和 t2 交替执行。添加 synchronized 关键字以后,t2 会在 t1 执行完成后执行,因此对于方法的锁定是成功的。
结果:









另外,需要注意的是 synchronized 是全局锁定,也就是说对于静态方法而言,它们会锁定全部有此标记的方法(尽管它们不是同一个方法);而对于对象实例,它们会锁定同一对象全部有此标记的方法(尽管它们不是同一个方法)。
7. 原子操作
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行倒结束,中间不会有任何线程切换操作。
通常所说的Java原子操作包括对非long和double型的primitive进行赋值,以及返回这两者之外的primitive。之所以要把它们排除在外是因为它们都比较大,而JVM的设计规范又没有要求读操作和赋值操作必须是原子操作(JVM可以试着去这么作,但并不保证)。不过如果你在long或double前面加了volatile,那么它就肯定是原子操作了。
看下面的例子,虽然 return i是一个原子操作,但是从获得i的值到方法返回之间有可能被其他线程修改,因此不要主观的认为下面的操作是原子操作。我们还是有必要为其添加同步关键字synchronized。另外 ++i 和 --i 都不是原子操作,它们都涉及读和写两个步骤。
public int getValue() { return i; }
《Thinking in Java》中关于最安全的做法提出了如下的方针,不过我不完全赞同。
- 如果你要synchronize类的一个方法,索性把所有的方法全都synchronize了。要判断,哪个方法该synchronize,哪个方法可以不synchronize,通常是很难的,而且也没什么把握。
- 删除synchronized的时候要绝对小心。通常这么做是为了性能,但是synchronized的开销在JDK1.3和1.4里已经大为降低了。此外,只有在用profiler分析过,确认synchronized确实是瓶颈的前提下才能这么作。
8. 线程协同
Java用对象锁来控制多线程安全,而所谓多线程协同无非是利用某种锁机制让线程暂时停顿下来,直到某个“信号”发生。为此,Java 将用来进行多线程协同的方法放在了根 Object 上,包括 wait(); notify(); notifyAll(); 。
调用 wait() / notify() / notifyAll() 之前必须先获取其对象锁,否则会抛出"IllegalMonitorStateException - current thread not owner" 异常。


















































输出
1
2
3
4
5
Notify Thread...
6
7
8
9
在上面这个例子中,当 i 等于 5 时,我们调用了对象锁 o 的 wait 方法阻塞线程。在 main 方法中我们循环检查对象状态,并适时发出信号结束等待。这个例子虽然很简单,但是由此可以处理多个线程之间的协同关系。当然,我们还可以给 wait 方法加一个参数,让其等待特定的时间,而不是上面例子中的无限制等待。
需要注意的是 wait() 会释放对象锁,sleep() 则不会。接着看下面的例子。
class MyThread extends Thread {
static Object o = new Object();
public void run() {
synchronized (o) {
int i = 0;
while (++i < 10) {
System.out.printf("%s - %d\n", Thread.currentThread().getName(), i);
try
{
if (i >= 5) o.wait();
}
catch (InterruptedException e)
{
}
}
}
}
}
public class Program {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
static Object o = new Object();
public void run() {
synchronized (o) {
int i = 0;
while (++i < 10) {
System.out.printf("%s - %d\n", Thread.currentThread().getName(), i);
try
{
if (i >= 5) o.wait();
}
catch (InterruptedException e)
{
}
}
}
}
}
public class Program {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
输出
t1 - 1
t1 - 2
t1 - 3
t1 - 4
t1 - 5
t2 - 1
t2 - 2
t2 - 3
t2 - 4
t2 - 5
9. 停止/中断线程
线程退出最好自己实现,在运行状态中一直检验一个状态,如果这个状态为真,就一直运行,如果外界更改了这个状态变量,那么线程就停止运行。
Java 不推荐使用 stop() / about() / suspend() / resume() 之类的方法来停止线程。原因包括:
- 在调用这些方法的时候,我们不能确定线程方法执行到何处,是否完成了特定的逻辑。
- 这些方法会让线程无法正确释放对象锁,可能造成死锁。
- 使用旗标(flag)。
- 调用 interrupt()。
class MyThread extends Thread {
public boolean stopFlag = false;
public void run() {
while (!stopFlag) {
try
{
System.out.println("Thread running, " + System.currentTimeMillis());
Thread.sleep(50);
}
catch (Exception e)
{
}
}
System.out.println("Thread Stop...");
}
}
public class Program {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try
{
Thread.sleep(100);
}
catch (Exception e)
{
}
t.stopFlag = true;
}
}
public boolean stopFlag = false;
public void run() {
while (!stopFlag) {
try
{
System.out.println("Thread running, " + System.currentTimeMillis());
Thread.sleep(50);
}
catch (Exception e)
{
}
}
System.out.println("Thread Stop...");
}
}
public class Program {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try
{
Thread.sleep(100);
}
catch (Exception e)
{
}
t.stopFlag = true;
}
}
当线程因某种原因处于阻塞等待状态时,我们就无法使用旗标终止它,那么改用interrupt()好了。
class MyThread extends Thread {
public void run() {
try
{
while (true) {
System.out.println("Thread running, " + System.currentTimeMillis());
synchronized (this) {
wait();
}
}
}
catch (Exception e)
{
}
System.out.println("Thread Stop...");
}
}
public class Program {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try
{
while (t.getState() != Thread.State.WAITING) {
Thread.sleep(500);
}
t.interrupt();
}
catch (Exception e)
{
}
}
}
public void run() {
try
{
while (true) {
System.out.println("Thread running, " + System.currentTimeMillis());
synchronized (this) {
wait();
}
}
}
catch (Exception e)
{
}
System.out.println("Thread Stop...");
}
}
public class Program {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try
{
while (t.getState() != Thread.State.WAITING) {
Thread.sleep(500);
}
t.interrupt();
}
catch (Exception e)
{
}
}
}
相关推荐
### Java线程学习知识点 #### 一、Java线程概览 - **定义与作用**:线程是在程序中独立且并发执行的路径。在Java中,线程被设计为语言的一部分,而不是作为操作系统的底层工具。每个Java程序至少包含一个主线程,在...
在Java编程语言中,线程是程序执行的基本单元,它允许程序并发地...同时,"Java线程学习和总结.files"目录下的文件可能是与文章相关的辅助资料,例如代码示例或图片。建议结合这些资料一起学习,以获得更全面的知识。
本资源"JAVA线程学习(源代码)"提供了关于Java线程的源代码示例,帮助我们深入理解和实践线程的使用。 首先,我们要理解Java中的线程模型。Java线程由`java.lang.Thread`类或`java.util.concurrent.Executor`框架来...
Java 线程学习笔记 Java 线程创建有两种方法: 1. 继承 Thread 类,重写 run 方法:通过继承 Thread 类并重写 run 方法来创建线程,这种方法可以使线程具有自己的执行逻辑。 2. 实现 Runnable 接口:通过实现 ...
### Java线程学习:深入理解线程生命周期与同步机制 #### 标题解析:Java线程学习 在Java编程语言中,线程是程序执行的基本单位之一,它允许并发执行多个任务,从而提高应用程序的效率和响应性。通过Java线程的...
### Java线程学习教程知识点详解 #### 一、教程概览 - **适用人群**: 本教程主要面向那些已经熟练掌握了Java语言基本语法和应用,但对于多线程和并发编程经验较少的Java开发者。 - **目标**: 学习者通过本教程的...
在"java线程学习一4"这个主题中,我们将会深入探讨Java中的多线程概念,以及如何通过源码理解和使用相关工具进行线程管理。 首先,我们需要理解Java中的线程创建方式。Java提供了两种主要的线程创建方法:继承...
以下是对Java线程学习的详细总结: 1. **线程的几个状态** - 新建(New):线程被创建但尚未启动。 - 运行(Runnable):线程已启动并可能正在CPU上执行。 - 阻塞(Blocked):线程正在等待获取某个锁或进入同步...
通过学习以上知识点,初学者可以对Java线程有基本的理解,逐步掌握并发编程的核心技能。实践中的线程例子将有助于巩固理论知识,加深对线程工作原理的把握。在学习过程中,不断编写和调试多线程程序,是提升技能的...
本文将深入探讨Java线程的学习要点,帮助你提升在多线程环境下的编程能力。 首先,我们要明白线程的基本概念。线程是操作系统分配CPU时间的基本单元,一个进程中可以有多个线程同时执行任务,这使得程序可以在同一...
本专题资料聚焦于Java线程的学习,包括从基础到进阶的各种知识点。 1. **线程创建方式**:Java提供了两种创建线程的方式,一是通过继承Thread类,重写run()方法;二是实现Runnable接口,然后创建Thread对象并传入...
总的来说,Java多线程学习涵盖了线程的创建、同步、通信、调度以及异常处理等多个方面,深入理解和掌握这些知识点对于提升Java程序的性能和复杂性至关重要。通过阅读提供的"Java多线程.pdf"文档,你可以进一步了解和...
java中多线程下载学习,又新增了断点的实现,可以实现暂停继续下载网络文件的功能
Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java多线程学习Java...
对于学习java线程的初学者是很有用的资料,让自己很快的上手,帮助自己学习很快的知识。。。