java多线程实用操作

线程控制基本方法
方    法                             功    能

isAlive()                     判断线程是否还“活”着,即当前run线程是否还未终止。

getPriority()               获得线程的优先级数值

setPriority()               设置线程的优先级数值

Thread.sleep()           将当前线程睡眠指定毫秒数

join()                         调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。

yield()                    
  让出CPU,当前线程进入就绪队列等待调度。

wait()                      
当前线程进入对象的wait pool。

notify()/notifyAll()      唤醒对象的wait
pool中的一个/所有等待线程。

run()和start()

这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用
run()方法,这是由Java的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。

isAlive方法实例:


 1 package com.Gavin.createthread;
2
3 public class TestIsAlive {
4
5 public static void main(String[] args) {
6 Thread6 t6 = new Thread6("t6");
7 t6.start();
8
9 for(int i = 0; i < 50; i++) {
10 // System.out.println(Thread.currentThread().getName()); //主线程
11 System.out.println("t6‘s name:" + t6.getName());
12 }
13 }
14
15 }
16
17 class Thread6 extends Thread {
18 public Thread6(String string) {
19 super(string);
20 }
21 public void run() {
22 System.out.println("thread is alive:" + Thread.currentThread().isAlive());
23
24 for(int i = 0; i < 50; i++) {
25 System.out.println("subThread:" + i);
26 }
27 }
28 }

interrupt/sleep方法:
  可以调用Thread的静态方法: public static void
sleep(long millis) throws InterruptedException
 
使得当前线程休眠(暂时停止执行millis毫秒)。
  由于是静态方法,sleep可以由类名直接调用:Thread.sleep(…)

使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有Synchronized同步块,其他线程仍然不同访问共享数据。注意该方法要捕获异常

比如有两个线程同时执行(没有Synchronized),一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没 有
Sleep()方法,只有高优先级的线程执行完成后,低优先级的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。

总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。


 1 package com.Gavin.createthread;
2
3 import java.util.Date;
4
5 public class TestInterrupt {
6 public static void main(String[] args) {
7 Thread1 t = new Thread1();
8 t.start();
9 /**
10 * api中称:中断线程
11 * Thread1线程与主线程开始并发,主线程让出10s,
12 * 然后调用interrupt强行终止Thread1线程
13 */
14 try {
15 Thread.sleep(10000);
16 } catch(InterruptedException e) {
17 }
18
19 t.interrupt();
20 }
21 }
22
23 class Thread1 extends Thread {
24 public void run() {
25 while (true) {
26 System.out.println("===" + new Date()+ "===");
27 try {
28 sleep(1000);
29 } catch (InterruptedException e) {
30 return;
31 }
32 }
33 }
34 }

停止线程的方法中,stop最强暴,其次便是interrupte,这两种都是不提倡的,推荐的方法是通过flag标志来终止线程,例如:


 1 package com.Gavin.createthread;
2 public class TestShutDown {
3 public static void main(String[] args) {
4 Thread5 t5 = new Thread5();
5 Thread t = new Thread(t5);
6 t.start();
7 for(int i = 0; i < 100; i++) {
8 System.out.println("main thread i:" + i);
9 }
10 System.out.println("main thread is over");
11 /**
12 * 通过操作flag标志来关闭线程,推荐使用
13 */
14 t5.shutDown();
15 // t.stop(); //太暴力,不推荐
16 }
17 }
18 class Thread5 implements Runnable {
19 private boolean flag = true;
20 public void run() {
21 int i = 0;
22 while(flag) {
23 System.out.println("value:" + i++);
24 }
25 }
26 public void shutDown() {
27 flag = false;
28 }
29 }

join方法:

            合并某个线程,,join()方法使调用该方法的线程在此之前执行完毕,也就是等待调用该方法的线程执行完毕后再往下继续执行。注意该方法也要捕获异常。


 1 package com.Gavin.createthread;
2
3 public class TestJoin {
4 public static void main(String[] args) {
5 //指定新的线程对象,并通过super指向Thread,指定线程名称
6 Thread2 t = new Thread2("Thread2 ");
7 t.start();
8 /**
9 * api中称:等待该线程终止。
10 * 当线程启动后,原本线程是会与主线程并发执行
11 * 当调用了join方法后,意味着Thread2线程将会与主线程合并
12 * 所以,需要等待Thread2线程执行完毕,合并后,主线程才会继续执行
13 */
14 try {
15 t.join();
16 } catch (InterruptedException e) {
17 }
18 for(int i = 0; i <= 10; i++) {
19 System.out.println("i am main thread " + i);
20 }
21 }
22 }
23
24 class Thread2 extends Thread {
25 Thread2(String string) {
26 super(string);
27 }
28 public void run() {
29 for(int i = 0; i <= 10; i++) {
30 System.out.println("i am " + getName() + i);
31 try {
32 /**
33 * api中称:在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),
34 * 此操作受到系统计时器和调度程序精度和准确性的影响
35 */
36 sleep(1000);
37 } catch (InterruptedException e) {
38 return;
39 }
40 }
41 }
42 }

yield方法:

            暂时让出CPU,给其他线程执行的机会,它与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。


 1 package com.Gavin.createthread;
2
3 public class TestYield {
4 public static void main(String[] args) {
5 Thread3 t = new Thread3("t");
6 Thread3 tt = new Thread3("tt");
7 t.start();
8 tt.start();
9 }
10 }
11 class Thread3 extends Thread {
12 Thread3(String string) {
13 super(string);
14 }
15 public void run () {
16 for(int i = 0; i < 100; i++) {
17 System.out.println(getName() + ":" + i);
18 if(i % 10 == 0) {
19 /**
20 * api中称:暂停当前正在执行的线程对象,并执行其他线程。
21 * 注:暂停时间片不定,只是到条件即暂时让出cpu
22 */
23 yield();
24 }
25 }
26 }
27 }

setPriority():


 1 package com.Gavin.createthread;
2
3 public class TestPriority {
4
5 public static void main(String[] args) {
6 Thread t1 = new Thread(new T1());
7 Thread t2 = new Thread(new T2());
8 /**
9 * 未设置优先级的,t1,t2将几乎拥有均等的时间片,交互执行
10 * 但是当设置优先级后,t1会拥有更长时间片。甚至t1在抢夺的时间片内已执行完。
11 */
12 t1.setPriority(Thread.NORM_PRIORITY + 3);
13
14 t1.start();
15 t2.start();
16 }
17
18 }
19
20 class T1 implements Runnable {
21 public void run() {
22 for(int i = 0; i < 200; i++) {
23 System.out.println("T1:" + i);
24 }
25 }
26 }
27
28 class T2 implements Runnable {
29 public void run() {
30 for(int i = 0; i < 200; i++) {
31 System.out.println("T2:" + i);
32 }
33 }
34
35 }

关键字Synchronized
这个关键字用于保护共享数据,当然前提是要分清哪些数据是共享数据。每个对象都有一个锁标志,当一个线程访问该对象时,被Synchronized修饰的数据将被“上锁”,阻止其他线程访问。当前线程访问完这部分数据后释放锁标志,其他线程就可以访问了。


 1 //同步锁
2 public class TestSync implements Runnable {
3 Timer timer = new Timer();
4 public static void main(String[] args) {
5 TestSync test = new TestSync();
6 Thread t1 = new Thread(test);
7 Thread t2 = new Thread(test);
8
9 //t1.setName("t1");
10 //t2.setName("t2");
11 t1.start();
12 t2.start();
13 }
14 public void run() {
15 timer.add(Thread.currentThread().getName());
16 }
17 }
18 class Timer{
19 private static int num = 0;
20
21 //synchronized 锁定当前对象
22 public synchronized void add(String name) {
23 //synchronized(this) {
24 num++;
25 try {
26 Thread.sleep(1);
27 } catch (InterruptedException e){
28
29 }
30 System.out.println(name + ",你是第" + num + "个使用timer的线程");
31 //}
32 }
33 }

注意以下这个例子


 1 public ThreadTest implements Runnable {
2 public synchronized void run(){
3 for(int i=0;i<10;i++) {
4 System.out.println(" " + i);
5 }
6 }
7 public static void main(String[] args) {
8 Runnable r1 = new ThreadTest();
9 Runnable r2 = new ThreadTest();
10 Thread t1 = new Thread(r1);
11 Thread t2 = new Thread(r2);
12 t1.start();
13 t2.start();
14 }
15 }

结果: 0 0 1 2 3 4 1 5 2 6 3 7 4 8 9 5 6 7 8 9 ;(不同对象)
以上这段程序中的 i
变量并不是共享数据,这个程序中的t1,t2分别是两个对象(r1,r2)的线程。JAVA是面向对象的程序设计语言,不同的对象的数据是不同
的,r1,r2有各自的run()方法,而synchronized使同一个对象的多个线程,在某个时刻只有其中的一个线程可以访问这个对象的
synchronized数据。

当把代码改成如下:Synchronized关键字才会起作用

Runnable r = new ThreadTest();

Thread t1 = new Thread(r);

Thread t2 = new Thread(r);

t1.start();

t2.start();

synchronized 导致的死锁问题:


 1 //死锁典型:哲学家吃饭问题
2 public class TestDeadLock implements Runnable{
3 public int flag = 1;
4 static Object o1 = new Object();
5 static Object o2 = new Object();
6 public void run() {
7 System.out.println("flag=" + flag);
8 if(flag == 1) {
9 synchronized(o1) {
10 try {
11 Thread.sleep(500);
12 }catch (InterruptedException e) {
13 e.printStackTrace();
14 }
15 synchronized(o2) {
16 System.out.println("1");
17 }
18 }
19 }
20
21 if(flag == 0) {
22 synchronized(o2) {
23 try {
24 Thread.sleep(500);
25 }catch (InterruptedException e) {
26 e.printStackTrace();
27 }
28 synchronized(o1) {
29 System.out.println("0");
30 }
31
32 }
33 }
34 }
35
36 public static void main(String[] args) {
37 TestDeadLock td1 = new TestDeadLock();
38 TestDeadLock td2 = new TestDeadLock();
39 td1.flag = 1;
40 td2.flag = 0;
41 Thread t1 = new Thread(td1);
42 Thread t2 = new Thread(td2);
43 t1.start();
44 t2.start();
45 }
46 }

wait()和notify()、notifyAll()

这三个方法用于协调多个线程对共享数据的存取,所以必须在Synchronized语句块内使用这三个方法。前面说过Synchronized这个
关键字用于保护共享数据,阻止其他线程对共享数据的存取。但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出Synchronized数据块时
让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。

wait()方法使当前线程暂停执行并释放对象锁标志,让其他线程可以进入Synchronized数据块,当前线程被放入对象等待池中。当调用
notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有

锁标志等待池中的线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。

notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

注意 这三个方法都是java.lang.Ojbect的方法!

时间: 2024-07-29 03:19:59

java多线程实用操作的相关文章

Android开发手记(27) Java多线程的操作

Java中常用的有关线程的操作有,判断线程是否启动.线程强制执行.线程休眠.线程中断.线程让步.线程同步等.下面就一一举例. 首先,我们新建一个MyThread类实现Runnable接口.基于此接口进行线程的相关操作. class MyThread implements Runnable { public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() +

Java 多线程IO简单实用Demo

多线程主要作用是充分利用Cpu,而不在于它的乱序性.本Demo不讲它竞争什么的.之前看过乱序打印ABC的例子什么的,那些有意义吗? 本Demo 是多线程打印文件夹下的文件,主要实现是用数组存放文件,一个游标遍历. 我们需要考虑在什么时候加互斥访问,本例用synchronized . 先考虑单线程的流程:客户端启动-->读取文件下的文件放到数组(IO)--> 取游标打印 ,游标加1 -- > 改文件写文件(IO) -- 重复上两步至越界 -- 结束 多线程时显然需要在"取游标打印

java多线程基本概念与简单实用

概述 程序:Program,是一个静态的概念 进程:Process,是一个动态的概念 进程是程序的一次动态执行过程, 占用特定的地址空间.每个进程都是独立的,由3部分组成cpu,data,code 缺点:内存的浪费,cpu的负担 线程:Thread,是进程中一个"单一的连续控制流程"  (a single sequential flow ofcontrol)/执行路径.线程又被称为轻量级进程(lightweight process). 一个进程可拥有多个并行的(concurrent)线

java多线程学习之——多线程中几种释放锁和不释放锁的操作

在学习java多线程这一块知识的时候,遇到了很多个关于线程锁什么时候释放的问题,现总结几种释放锁和不释放锁的操作如下: 不释放锁: 线程执行同步代码块或同步方法时,程序调用Thread.sleep(Long l).Thread.yield()方法暂停当前线程的执行 线程执行同步代码块时,其它线程调用该线程suspend()方法将该线程挂起,该线程不会释放锁(同步监视器) 尽量避免使用suspend()和resume()来控制线程 释放锁: 当前线程的同步方法.同步代码块执行结束 当前线程的同步方

Java多线程对同一个对象进行操作

示例: 三个窗口同时出售20张票. 程序分析: 1.票数要使用一个静态的值. 2.为保证不会出现卖出同一张票,要使用同步锁. 3.设计思路:创建一个站台类Station,继承THread,重写run方法,在run方法内部执行售票操作! 售票要使用同步锁:即有一个站台卖这张票时,其他站台要等待这张票卖完才能继续卖票! package com.multi_thread; //站台类 public class Station extends Thread { // 通过构造方法给线程名字赋值 publ

[转]Java多线程干货系列—(一)Java多线程基础

Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的执行单元线程本身依靠程序进行运行线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 2 进程:执行中的程序一个进程至少包含一个线程 3 单线程:程序中只存在一个线程,实际上主方法就是一个主线程 4

[转载] java多线程学习-java.util.concurrent详解(一) Latch/Barrier

转载自http://janeky.iteye.com/blog/769965 Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效.易维护.结构清晰的Java多线程程序.从这篇blog起,我将跟大家一起共同学习这些新的Java多线程构件 1. CountDownLatch     我们先来学习一下JDK1.5 API中关于这个类的详细介绍: “一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个

第12篇-JAVA 多线程

第12篇-JAVA 多线程 每篇一句 :不要只看到艰难,要看艰难后面的胜利 初学心得: 敢于尝试,就等于你已经向成功迈出了第一步 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-20| JAVA 多线程 ] 1.进程与线程 1.什么是进程 程序是指令和数据的有序的集合,其本身没有任何运行的含义,是一个静态的概念 进程是一个具有一定独立功能的程序,一个实体 几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程 当一个程序运行时,内部可

Java多线程基础(一)

线程与进程 1 线程:进程中负责程序执行的执行单元线程本身依靠程序进行运行线程是程序中的顺序控制流,只能使用分配给程序的资源和环境 2 进程:执行中的程序一个进程至少包含一个线程 3 单线程:程序中只存在一个线程,实际上主方法就是一个主线程 4 多线程:在一个程序中运行多个任务目的是更好地使用CPU资源 5  在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性. 每个对象都对应于一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访问对象用关键字synchr