基础知识《四》---Java多线程学习总结
本文转载自51cto
一、线程的基本概念
简单的说:线程就是一个程序里不同的执行路径,在同一个时间点上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();  //拿到当前线程
六、join和yield方法
t.join(); //t的run()方法完才会继续执行当前线程方法体
//也就是两个线程变成了一个线程
join方法的功能就是使异步执行的线程变成同步执行。也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法。如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完。
下面的代码演示了join的用法。
package mythread; public class JoinThread extends Thread
{
public static int n = 0; static synchronized void inc()
{
n++;
}
public void run()
{
for (int i = 0; i < 10; i++)
try
{
inc();
sleep(3); // 为了使运行结果更随机,延迟3毫秒 }
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{ Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++) // 建立100个线程
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++) // 运行刚才建立的100个线程
threads[i].start();
if (args.length > 0)
for (int i = 0; i < threads.length; i++) // 100个线程都执行完后继续
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
在例程2-8中建立了100个线程,每个线程使静态变量n增加10。如果在这100个线程都执行完后输出n,这个n值应该是1000。
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(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
//哪个线程体执行此方法,哪个线程让步
 public class TestYield {
   public static void main(String[] args) {
     MyThread3 t1 = new MyThread3("t1");
     MyThread3 t2 = new MyThread3("t2");
     t1.start(); t2.start();
   }
 }
 class MyThread3 extends Thread {
   MyThread3(String s){super(s);}
   public void run(){
     for(int i =1;i<=100;i++){
       System.out.println(getName()+": "+i);
       if(i%10==0){
         yield();
       }
     }
   }
 } 
七、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
八、线程优先级别 
线程的优先级用数字表示,范围从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.线程死锁
 public class TestDeadLock implements Runnable {
     public int flag = 1;
     static Object o1 = new Object(), o2 = new Object();
     public void run() {
 System.out.println("flag=" + flag);
         if(flag == 1) {
             synchronized(o1) {
                 try {
                     Thread.sleep(500);
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
                 synchronized(o2) {
                     System.out.println("1");
                 }
             }
         }
         if(flag == 0) {
             synchronized(o2) {
                 try {
                     Thread.sleep(500);
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
                 synchronized(o1) {
                     System.out.println("0");
                 }
             }
         }
     }      
     public static void main(String[] args) {
         TestDeadLock td1 = new TestDeadLock();
         TestDeadLock td2 = new TestDeadLock();
         td1.flag = 1;
         td2.flag = 0;
         Thread t1 = new Thread(td1);
         Thread t2 = new Thread(td2);
         t1.start();
         t2.start();  
     }
 } 
十、生产者消费者问题
 public class ProducerConsumer {
     public static void main(String[] args) {
         SyncStack ss = new SyncStack();
         Producer p = new Producer(ss);
         Consumer c = new Consumer(ss);
         new Thread(p).start();
         new Thread(p).start();
         new Thread(p).start();
         new Thread(c).start();
     }
 }  
 class WoTou {
     int id;
     WoTou(int id) {
         this.id = id;
     }
     public String toString() {
         return "WoTou : " + id;
     }
 }  
 class SyncStack {        //栈实现
     int index = 0;
     WoTou[] arrWT = new WoTou[6];    //相当于装物品的篮子  
     public synchronized void push(WoTou wt) {    //生产物品,线程安全
         while(index == arrWT.length) {        //当篮子满了线程等待
             try {
                 this.wait();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }  
         }
         this.notifyAll();    //开始生产时,叫醒等待的其他线程开始消费
         arrWT[index] = wt;
         index ++;
     }  
     public synchronized WoTou pop() {        //消费物品,线程安全
         while(index == 0) {            //如果篮子空了
             try {
                 this.wait();        //线程等待,等待生产者开始
 //生产,叫醒此线程
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }  
         }
         this.notifyAll();            //消费时喊醒生产者生产
         index--;
         return arrWT[index];
     }
 }  
 class Producer implements Runnable {            //生产者类
     SyncStack ss = null;
     Producer(SyncStack ss) {
         this.ss = ss;
     }  
     public void run() {
         for(int i=0; i<20; i++) {    //生产20个
             WoTou wt = new WoTou(i);
             ss.push(wt);
             System.out.println("生产了:" + wt);
             try {
                 Thread.sleep((int)(Math.random() * 200));
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
     }
 }  
 class Consumer implements Runnable {
     SyncStack ss = null;
     Consumer(SyncStack ss) {
         this.ss = ss;
     }  
     public void run() {
         for(int i=0; i<20; i++) {        //消费20个
             WoTou wt = ss.pop();
             System.out.println("消费了: " + wt);
             try {
                 Thread.sleep((int)(Math.random() * 1000));
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
     }
 }  
基础知识《四》---Java多线程学习总结的更多相关文章
- Java多线程学习(四)等待/通知(wait/notify)机制
		转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ... 
- 转:Java多线程学习(总结很详细!!!)
		Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ... 
- Java多线程学习(吐血超详细总结)
		Java多线程学习(吐血超详细总结) 林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实 ... 
- [转]Java多线程学习(总结很详细!!!)
		Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ... 
- Java多线程学习笔记
		进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ... 
- Java多线程学习(转载)
		Java多线程学习(转载) 时间:2015-03-14 13:53:14 阅读:137413 评论:4 收藏:3 [点我收藏+] 转载 :http://blog ... 
- java多线程学习笔记——详细
		一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ... 
- Java多线程学习(六)Lock锁的使用
		系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ... 
- Java多线程学习(五)线程间通信知识点补充
		系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ... 
- Java多线程学习(三)volatile关键字
		转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79680693 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ... 
随机推荐
- [转]Java总结篇系列:Java泛型
			一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ... 
- SQLHelper---赵晓虎(简洁,全面)
			public static class SQLHelper { //获取连接字符串,,首先添加对configuration的引用 private static string connStr = Con ... 
- 在CentOS上装 ElasticSearch
			参考官方文档:Install Elasticsearch with RPM ElasticSearch依赖Java,所以需要先安装Java: 到Oracle官网找到下载链接 http://www.or ... 
- 读JS高级API笔记_(DOM&&DOM2&&DOM3)哎呀——园龄才9个月啊
			---恢复内容开始--- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ... 
- Java基础-转义字符
			Java中的字符占两个字节.一些常用的转义字符: ①\r表示接受键盘输入,相当于按下了回车键: ②\n表示换行: ③\t表示制表符,相当于Table键: ④\b表示退格键,相当于Back Space键 ... 
- POJ3749 破译密码
			Description 据说最早的密码来自于罗马的凯撒大帝.消息加密的办法是:对消息原文中的每个字母,分别用该字母之后的第5个字母替换(例如:消息原文中的每个字母A都分别替换成字母F).而你要获得消息 ... 
- poj 3463   最短路与次短路&&统计个数
			题意:求最短路和比最短路长度多1的次短路的个数 本来想图(有)方(模)便(版)用spfa的,结果妹纸要我看看dijkstra怎么解.... 写了三遍orz Ver1.0:堆优化+邻接表,WA //不能 ... 
- 洛谷P3386 【模板】二分图匹配
			匈牙利算法模板 /*by SilverN*/ #include<algorithm> #include<iostream> #include<cstring> #i ... 
- Codeforces 593B Anton and Lines
			LINK time limit per test 1 second memory limit per test 256 megabytes input standard input output st ... 
- Linux X Window System运行原理和启动过程
			本文主要说明X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System. 一) 基本运行原理 X Window System采用C/S结构,但和我们常见 ... 
