Java多线程的理解和实例

编写具有多线程程序经常会用到的方法:run(), start(), wait(), notify(), notifyAll(), sleep(), yield(), join()

还有一个关键字:synchronized

下面主要来讲讲:

线程的创建方式就不需要细说,就2种方式 Thread和Runnable

1.run()和start()

实例1:

public class ThreadTest extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}

public static void main(String[] args) {
new ThreadTest().start();
new ThreadTest().start();
}
}

这是一个简单的多线程例子

实例2:

public class ThreadTest implements Runnable {

public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}

public static void main(String[] args) {
Runnable r1 = new ThreadTest();
Runnable r2 = new ThreadTest();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}

在这个例子中,run被加上了synchronized,这个程序输出的结果是什么呢?t1和t2是2个对象的线程,不同对象的线程是不同的,所以在这个程序中synchronized 并没有起到作用,对于synchronized的定义来说,是针对同一对象的多个线程来说的,在某一时刻只有一个线程能访问此对象的数据

实例3:

public class ThreadTest implements Runnable {
public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}

public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();

t2.start();
}
}

实例4:

public class ThreadTest implements Runnable {
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print(" " + i);
}
}
}

public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}

实例3和4中,synchronized控制了线程对象的数据共享,输出的结果只能是0123456789,3和4其实区别就是synchronized作用范围

实例5:

public class ThreadTest implements Runnable {
public void run() {
for (int k = 0; k < 5; k++) {
System.out.println(Thread.currentThread().getName()
+ " : for loop : " + k);

}
synchronized (this) {
for (int k = 0; k < 5; k++) {
System.out.println(Thread.currentThread().getName()
+ " : synchronized for loop : " + k);
}
}
}

public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1_name");
Thread t2 = new Thread(r, "t2_name");
t1.start();
t2.start();
}
}

输出结果是:

t1_name : for loop : 0
t1_name : for loop : 1
t1_name : for loop : 2
t2_name : for loop : 0
t1_name : for loop : 3
t2_name : for loop : 1
t1_name : for loop : 4
t2_name : for loop : 2
t1_name : synchronized for loop : 0
t2_name : for loop : 3
t1_name : synchronized for loop : 1
t2_name : for loop : 4
t1_name : synchronized for loop : 2
t1_name : synchronized for loop : 3
t1_name : synchronized for loop : 4
t2_name : synchronized for loop : 0
t2_name : synchronized for loop : 1
t2_name : synchronized for loop : 2
t2_name : synchronized for loop : 3
t2_name : synchronized for loop : 4

第一个for循环没有收synchronized保护,所以t1,t2的执行方式是交错的,第二个循环受synchronized保护,所以结果是有规律的

2.sleep()方法:

实例6:

public class ThreadTest implements Runnable {
public void run() {

for (int k = 0; k < 5; k++) {
  if (k == 2) {
  try {
    Thread.currentThread().sleep(5000);
  }
  catch (Exception e) {}
  }
    System.out.println(Thread.currentThread().getName()+ " : " + k);
  }
}

public static void main(String[] args) {
  Runnable r = new ThreadTest();
  Thread t1 = new Thread(r, "t1_name");
  Thread t2 = new Thread(r, "t2_name");
  t1.setPriority(Thread.MAX_PRIORITY);
  t2.setPriority(Thread.MIN_PRIORITY);
  t1.start();
  t2.start();
}
}

输出结果:

t1_name : 0
t1_name : 1
t2_name : 0
t2_name : 1
t1_name : 2
t1_name : 3
t1_name : 4
t2_name : 2
t2_name : 3
t2_name : 4

t1被设置了最高的优先级,t2被设置了最低的优先级,t1不执行完,t2就没有机会执行。但由于t1在执行的中途休息了5秒中,这使得t2就有机会执行了。

3.join()方法:主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码

实例7:

public class ThreadTest implements Runnable {
public static int a = 0;
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
}

public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t = new Thread(r);
t.start();
System.out.println(a);
}
}

实例8:

public class ThreadTest implements Runnable {
public static int a = 0;
public void run() {
for (int k = 0; k < 5; k++) {
a = a + 1;
}
public static void main(String[] args) throws Exception {
Runnable r = new ThreadTest();
Thread t = new Thread(r);
t.start();
t.join();
System.out.println(a);
}
}

实例7和8区别就在于加了个join方法,join能保证调用此方法的线程对象完成对应run方法中的内容,所以实例7来说,不确定输出的是什么,而实例8肯定输出的是5

4.yield()方法:

yield() 方法与sleep() 方法相似,只是它不能由用户指定线程暂停多长时间。按照SUN的说法:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。而yield()方法只能使同优先级的线程有执行的机会。

实例9:

public class ThreadTest implements Runnable {
public void run() {
8
for (int k = 0; k < 5; k++) {
if (k == 5 && Thread.currentThread().getName().equals("t1")) {
Thread.yield();
}
System.out.println(Thread.currentThread().getName()
+ " : " + k);
}
}

public static void main(String[] args) {
Runnable r = new ThreadTest();
Thread t1 = new Thread(r, "t1");
Thread t2 = new Thread(r, "t2");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
}
}

输出结果:

t1 : 0
t1 : 1
t1 : 2
t1 : 3
t1 : 4

t2 : 0
t2 : 1
t2 : 2
t2 : 3
t2 : 4

从输出结果上看,yield() 方法不会使不同优先级的线程有执行的机会。本例中t1和t2不同的优先级,在t1被yield的时候,t2也是一点机会也没有,只有等到高优先级t1执行完成之后才有执行的机会,而sleep并不是,可以看看实例6

5.wait(),notify(),notifyAll()

首先说明:wait(), notify(),notifyAll()
这些方法由java.lang.Object类提供,而上面讲到的方法都是由java.lang.Thread类提供(Thread类实现了Runnable接口)。

这三个方法用于协调多个线程对共享数据的存取,所以这三个方法只能在synchronized中使用

实例10:

public class ThreadTest implements Runnable {
  public static int shareVar = 0;
  public synchronized void run() {
    if (shareVar == 0) {
    for (int i = 0; i < 10; i++) {
      shareVar++;
      if (shareVar == 5) {
        try {
          this.wait();
        }
        catch (Exception e) {}
      }
     }
    }
  if (shareVar != 0) {
    System.out.print(Thread.currentThread().getName());
    System.out.println(" shareVar = " + shareVar);
    this.notify();
  }
}

public static void main(String[] args) {
  Runnable r = new ThreadTest();
  Thread t1 = new Thread(r, "t1");
  Thread t2 = new Thread(r, "t2");
  t1.start();
  t2.start();
}
}

输出结果:

t2 shareVar = 5
t1 shareVar = 10

过程:t1线程最先执行。由于初始状态下shareVar为0,t1将使shareVar连续加1,当shareVar的值为5时,t1调用wait() 方法,
t1将处于休息状态,同时释放锁标志。这时t2得到了锁标志开始执行,shareVar的值已经变为5,所以t2直接输出shareVar的值,

然后再调用notify()
方法唤醒t1。t1接着上次休息前的进度继续执行,把shareVar的值一直加到10,由于此刻shareVar的值不为0,
所以t1将输出此刻shareVar的值,然后再调用notify()
方法,由于此刻已经没有等待锁标志的线程,所以此调用语句不起任何作用。

时间: 2024-11-12 10:49:29

Java多线程的理解和实例的相关文章

有关JAVA多线程的理解

不同于c++等语言的调用操作系统的线程调控机制来实现多线程,java语言内置了多线程的api包,因此可以更加方便的使用多线程技术.(1)线程的问题.进程是程序的一次动态执行过程,它对应了从代码加载.执行至执行完毕的一个完整过程,这个过程也是进程本身从产生.发展至消亡的过程.线程是比进程更小的单位,一个进程执行过程中可以产生多个线程,每个线程有自身的产生.存在和消亡的过程,也是一个动态的概念.每个进程都有一段专用的内存区域,而线程间可以共享相同的内存区域(包括代码和数据),并利用这些共享单元来实现

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

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

synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁,源码剖析 第一部分:synchronized与static synchronized的差别 1.synchronized与static synchronized 的差别 synchronized是对类的当前实例进行加锁,防止其它线程同一时候訪问该类的该实例的全部synchronized块.注意这里

synchronized与static synchronized 的区别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为如下部分: 第一部分:synchronized与static synchronized 的区别 第二部分:JVM底层又是如何实现synchronized的 第三部分:Java多线程锁,源代码剖析 第一部分:synchronized与static synchronized的区别 1.synchronized与static synchronized 的区别 synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是"类

Java多线程深入理解

在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 对于直接继承Thread的类来说,代码大致框架是: ? 1 2 3 4 5 6 7 8 9 10 11 class 类名 extends Thread{  方法1;  方法2:  -  public void run(){  // other code-  }  属性1:  属性2:  -  }  先看一个简单的例子: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

跟着实例学习java多线程9-定时任务实例

定时任务是我们经常遇到的业务场景,我们有很多的功能都需要这样的技术来实现,例如:定时获取一些数据push出去,定时处理一些清理任务,定时检查某个值等.那么我们该怎么实现,在实现中又该注意一些什么? 定时任务就是另开一个线程来执行,其实也是并发的一类,大家可能不好理解,说定时不就是到时间执行一下,怎么还会产生并发,这里主要是看两个指标,一是看执行频率,二是看每次执行的时间,如果执行频率高并且执行任务又会很耗时,那么这时候就形成了并发,当然还有一种情况那就是,定时的job中调用其它服务的方法,而正常

Java多线程的理解

一个线程创建之后,总是处于其生命周期的4个状态之一中.线程的状态表明此线程当前正在进行的活动,而线程的状态是可以通过程序来进行控制的,就是说,可以对线程进行操作来改变状态.这些操作包括启动(start).终止(stop).睡眠(sleep).挂起 (suspend).恢复(resume).等待(wait)和通知(notify).每一个操作都对应了一个方法,这些方法是由软件包java.lang提供的. ①创建(new)状态 如果创建了一个线程而没有启动它,那么,此线程就处于创建状态.比如,下述语句

java 多线程的理解 黑马程序员

public class MultiThread { public static void main(String args[]) { System.out.println("我是主线程!"); //下面创建线程实例thread1 ThreadUseExtends thread1=new ThreadUseExtends(); //创建thread2时以实现了Runnable接口的THhreadUseRunnable类实例为参数 Thread thread2=new Thread(ne

Java 多线程ServerSocket通讯简单实例(基于TCP协议)

首先是建立一个类继承Thread类 package com.zzq.socket;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket; public class