基础知识《四》---Java多线程学习总结

一、线程的基本概念
简单的说:线程就是一个程序里不同的执行路径,在同一个时间点上cpu只会有一个线程在执行,Java里的多线程是通过java.lang.Thread类来实现的,每个线程都拥有自己独立的方法栈空间。

二、java线程的创建和启动
第一种
定义线程类实现Runnable接口:
Thread myThread = new Thread(target) //target为Runnable接口类型
Runnable中只有一个方法:
public void run();用以定义线程运行体
第二种
可以定义一个Thread的子类并重写其run方法:
clas MyThread extends Thread{
public void run(){}
}
线程类必须通过执行Thread的start()方法启动一个新的线程,如果调用run()方法是属于方法的调用,不会启动一个新的线程,推荐使用第一种方式创建线程,使用接口较为灵活。

三、线程状态装换
调用线程start()方法时,线程进入就绪状态,Cpu分配时间片,线程进入运行状态,时间片结束,run()方法未执行完,线程进入阻塞状态。

四、线程控制基本方法
 isAlive() //判断线程是否还“活着”,即线程是否还未终止
getPriority() //获得线程的优先级数值
setPriority() //设置线程的优先级指数
Thread.sleep() //静态方法,将当前线程睡眠指定毫秒数
join()  //调用某线程的该方法,将当前线程与该线程合并,
//即等待该线程结束,再回复当前线程的运行。
yield()  //让出CPU,当前线程进入就绪状态等待调度
interrupt() //中断线程
wait()  //当前线程进入对象的wait pool
notify()/notifyAll //唤醒对象的wait pool中的一个/所有等待线程

五、sleep方法
Thread的静态方法
public static void sleep(long millis)throws InterruptedException
必须对异常进行捕捉
Thread.currentThread();  //拿到当前线程

六、interrupt方法一种让线程退出的方式。

 1 import java.util.*;
 2 public class TestInterrupt{
 3     public static void main(String[] args){
 4         MyThread t = new MyThread();
 5         t.start();
 6         try{Thread.sleep(10000);}
 7         catch(InterruptedException i){}
 8         t.interrupt();
 9     }
10 }
11
12 class MyThread extends Thread{
13     public void run(){
14         while(true){
15             try{
16                 System.out.println("------"+new Date()+"-----");
17                 Thread.sleep(1000);
18             }catch(InterruptedException i){
19                 return;
20             }
21         }
22     }
23 }
24  

七、join和yield方法 
t.join(); //t的run()方法完才会继续执行当前线程方法体
//也就是两个线程变成了一个线程

join方法的功能就是使异步执行的线程变成同步执行。也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法。如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完。

下面的代码演示了join的用法。

 1 package mythread;
 2
 3 public class JoinThread extends Thread
 4 {
 5     public static int n = 0;
 6
 7     static synchronized void inc()
 8     {
 9         n++;
10     }
11     public void run()
12     {
13         for (int i = 0; i < 10; i++)
14             try
15             {
16                 inc();
17                 sleep(3);  // 为了使运行结果更随机,延迟3毫秒
18
19             }
20             catch (Exception e)
21             {
22             }
23     }
24     public static void main(String[] args) throws Exception
25     {
26
27         Thread threads[] = new Thread[100];
28         for (int i = 0; i < threads.length; i++)  // 建立100个线程
29             threads[i] = new JoinThread();
30         for (int i = 0; i < threads.length; i++)   // 运行刚才建立的100个线程
31             threads[i].start();
32         if (args.length > 0)
33             for (int i = 0; i < threads.length; i++)   // 100个线程都执行完后继续
34                 threads[i].join();
35         System.out.println("n=" + JoinThread.n);
36     }
37 }  

在例程2-8中建立了100个线程,每个线程使静态变量n增加10。如果在这100个线程都执行完后输出n,这个n值应该是1000。

1.  测试1

使用如下的命令运行上面程序:

  1. java mythread.JoinThread

程序的运行结果如下:

n=442

这个运行结果可能在不同的运行环境下有一些差异,但一般n不会等于1000。从上面的结果可以肯定,这100个线程并未都执行完就将n输出了。

2.  测试2

使用如下的命令运行上面的代码:

在上面的命令行中有一个参数join,其实在命令行中可以使用任何参数,只要有一个参数就可以,这里使用join,只是为了表明要使用join方法使这100个线程同步执行。

程序的运行结果如下:

n=1000

无论在什么样的运行环境下运行上面的命令,都会得到相同的结果:n=1000。这充分说明了这100个线程肯定是都执行完了,因此,n一定会等于1000。

t.yield(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
//哪个线程体执行此方法,哪个线程让步

 1 public class TestYield {
 2   public static void main(String[] args) {
 3     MyThread3 t1 = new MyThread3("t1");
 4     MyThread3 t2 = new MyThread3("t2");
 5     t1.start(); t2.start();
 6   }
 7 }
 8 class MyThread3 extends Thread {
 9   MyThread3(String s){super(s);}
10   public void run(){
11     for(int i =1;i<=100;i++){
12       System.out.println(getName()+": "+i);
13       if(i%10==0){
14         yield();
15       }
16     }
17   }
18 } 

八、线程优先级别 
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级为5.
Thread.MAX_PRIORITY=1
Thread.MIN_PRIORITY=10
Thread.NORM_PRIORITY=5
例:t.setPriority(Thread.NORM_PRIORITY+3);
九、线程同步
1.同步代码块
synchronized(this){  //在执行代码块过程中,不会被其他线程打断
...  
}
public sunchronized void method //执行此方法时,当前对象被锁定
在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性,每个对象 都对应一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访 问该对象。
2.线程死锁

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

十、生产者消费者问题

 1 public class ProducerConsumer {
 2     public static void main(String[] args) {
 3         SyncStack ss = new SyncStack();
 4         Producer p = new Producer(ss);
 5         Consumer c = new Consumer(ss);
 6         new Thread(p).start();
 7         new Thread(p).start();
 8         new Thread(p).start();
 9         new Thread(c).start();
10     }
11 }
12
13 class WoTou {
14     int id;
15     WoTou(int id) {
16         this.id = id;
17     }
18     public String toString() {
19         return "WoTou : " + id;
20     }
21 }
22
23 class SyncStack {        //栈实现
24     int index = 0;
25     WoTou[] arrWT = new WoTou[6];    //相当于装物品的篮子
26
27     public synchronized void push(WoTou wt) {    //生产物品,线程安全
28         while(index == arrWT.length) {        //当篮子满了线程等待
29             try {
30                 this.wait();
31             } catch (InterruptedException e) {
32                 e.printStackTrace();
33             }
34
35         }
36         this.notifyAll();    //开始生产时,叫醒等待的其他线程开始消费
37         arrWT[index] = wt;
38         index ++;
39     }
40
41     public synchronized WoTou pop() {        //消费物品,线程安全
42         while(index == 0) {            //如果篮子空了
43             try {
44                 this.wait();        //线程等待,等待生产者开始
45 //生产,叫醒此线程
46             } catch (InterruptedException e) {
47                 e.printStackTrace();
48             }
49
50         }
51         this.notifyAll();            //消费时喊醒生产者生产
52         index--;
53         return arrWT[index];
54     }
55 }
56
57 class Producer implements Runnable {            //生产者类
58     SyncStack ss = null;
59     Producer(SyncStack ss) {
60         this.ss = ss;
61     }
62
63     public void run() {
64         for(int i=0; i<20; i++) {    //生产20个
65             WoTou wt = new WoTou(i);
66             ss.push(wt);
67             System.out.println("生产了:" + wt);
68             try {
69                 Thread.sleep((int)(Math.random() * 200));
70             } catch (InterruptedException e) {
71                 e.printStackTrace();
72             }
73         }
74     }
75 }
76
77 class Consumer implements Runnable {
78     SyncStack ss = null;
79     Consumer(SyncStack ss) {
80         this.ss = ss;
81     }
82
83     public void run() {
84         for(int i=0; i<20; i++) {        //消费20个
85             WoTou wt = ss.pop();
86             System.out.println("消费了: " + wt);
87             try {
88                 Thread.sleep((int)(Math.random() * 1000));
89             } catch (InterruptedException e) {
90                 e.printStackTrace();
91             }
92         }
93     }
94 }  
时间: 2024-08-07 04:31:52

基础知识《四》---Java多线程学习总结的相关文章

基础知识:Java多线程编程

关于线程和进程 ? ? 线程是进程的一个执行单元,它和进程一样拥有独立的执行控制,由操作系统负责调度,它们俩的区别可以用一句话概括之,那就是进程是程序的一次执行,而线程可以理解为进程执行的一段程序片段,也就是说它们是一种包含关系,线程不能独立运行,必须依存在进程之中 ? ? 另外从资源分配的角度上看,进程是系统进行资源分配和调度的一个独立单位,而线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资

java基础知识《JAVA 核心技术》学习笔记(一)

一:数据类型 (1)java整形: 类型                         存储要求 int                              4字节 short                          2字节 long                           8字节 byte                           1字节 (2)浮点类型 类型                         储存要求 float            

[转]Java多线程学习(总结很详细!!!)

Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的线程函数用法.概述等.首先让我们来了解下在操作系统中进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,

C# 基础知识 (四).C#简介及托管代码

        暑假转瞬即逝,从10天的支教生活到1周的江浙沪旅游,在这个漫长的暑假中我经历了很多东西,也学到了很多东西,也认识到了很多不足之处!闲暇之余我准备重新进一步巩固C#相关知识,包括C#入门知识.C#并行开发.ASP网站等.这篇文章我介绍的是书籍--C#入门经典(Beginning C#) 作者Karli Watson.主要包括的是我自己缺乏的一些C#简介知识和托管代码的内容.内容比较简单,参照该书籍较多,相当于自己的在线笔记!                             

java多线程学习(3)

1)竞争条件 在实际的多线程应用中,通常会有两个或多个线程需要对共同的对象进行共享访问,如果两个线程访问相同的对象,而且每一个都调用了一个会改变对象状态的方法, 那么,线程就会相互倾轧.根据各个线程访问数据的不同顺序,可能会产生腐蚀现象.这种情况通常称为竞争条件. 2)同步 为了多个线程对共享数据的腐蚀,就需要对数据的存取实现同步:常用的同步方法有3种: 1.Reenlock 用Reenlock保护代码块的基本机构如下: 1 Lock myLock=new ReenLock; 2 3 myLoc

java多线程学习(2)

1)Callable和Future Runnable封装一个异步运行的任务:可以当成一个没有任何参数和返回值的异步方法,Callable和 Runnable类似,但是它有返回值和参数. Callable接口是一个参数化的类型,只有一个方法call. 1 public interface Callable<V> 2 3 { 4 5 V call()throws Exception; 6 7 } 类型参数v是指返回值的类型,例如Callable<Integer>代表最终返回一个Inte

java多线程学习(1)

1)多线程与多进程的区别 多线程和多进程有什么区别呢?本质的区别在于每个进程有它自己的变量的完备集,线程则共享相同的数据. 对程序来说,共享的变量会使得线程之间的通信比进程间的通信更加有效和简单:同时,线程相对于进程来说,更加的“轻量级”, 线程的创建和销毁要比 进程的 开销要小的多. 2)多线程程序的构造 多线程的构造通常有两种方法, 第一种方法是,构建一个Thread的子类,并重写它的run()方法: 1 class MyThread extends Thread 2 { 3 4 publi

java多线程学习--java.util.concurrent

CountDownLatch,api 文档:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. 假设我们要打印1-100,最

java 多线程学习(一)

1 public class ThreadA extends Thread { 2 private static int threadID = 0; 3 4 public ThreadA() { 5 super("ThreadID:" + (++threadID)); 6 } 7 8 public void run() { 9 try { 10 System.out.println(getName() + " 线程运行开始!"); 11 for (int i = 0

黑马程序员之Java多线程学习

android培训  java培训 期待与您交流! 这一篇文章主要关于java多线程,主要还是以例子来驱动的.因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,呵呵.大家可以去参考一些那些书籍.我这个文章主要关于实际的一些问题.同时也算是我以后复习的资料吧,.呵呵大家多多指教. 同时希望多结交一些技术上的朋友.谢谢. -------------------------------------------------------------------------------------