转 java多线程学习总结
此文转载 小舒的java世界 http://www.blogjava.net/zhengshuli-j2ee/articles/258068.html
关于 java多线程学习总结
小弟的第二篇j2se学习笔记,如果有错误或者遗漏的地方,还恳请各位高手老鸟们不要见笑,多给小弟一些批评,建议!
一、线程的基本概念
简单的说:线程就是一个程序里不同的执行路径
在同一个时间点上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()/all //唤醒对象的wait pool中的一个/所有等待线程
四、sleep方法
Thread的静态方法
public static void sleep(long millis)throws InterruptedException
必须对异常进行捕捉
Thread.currentThread(); //拿到当前线程
五、interrupt方法一种让线程退出的方式。
public class TestInterrupt{
public static void main(String[] args){
MyThread t = new MyThread();
t.start();
try{Thread.sleep(10000);}
catch(InterruptedException i){}
t.interrupt();
}
}
class MyThread extends Thread{
public void run(){
while(true){
try{
System.out.println("------"+new Date()+"-----");
Thread.sleep(1000);
}catch(InterruptedException i){
return;
}
}
}
}
六、join和yield方法
t.join(); //t的run()方法完才会继续执行当前线程方法体
//也就是两个线程变成了一个线程
t.yield(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
//哪个线程体执行此方法,哪个线程让步
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();
}
}
}
}
七、线程优先级别
线程的优先级用数字表示,范围从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 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 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();
}
}
}
}