Java 多线程机制


一、线程的基本概念

线程是一个程序内部的顺序控制流。

线程和进程的区别:
每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
多进程:在操作系统中能同时运行多个任务(程序)
多线程:在同一应用程序中有多个顺序流同时执行

Java的线程是通过 java.lang.Thread 类实现的
VM 启动时会有一个由主方法(public static void main(){})所定义的线程。
每个线程都是通过某个特定的 Thread 对象所对应的方法run()来完成其操作的,方法run()称为线程体
通过调用 Thread 类的start()方法来启动一个线程

二、线程的创建和启动


可以有两种方法创建新的线程

第一种

定义线程类实现 Runnable接口
Thread myThread = new Thread (Target)  //target 为 Runnable 接口类型

Runnable 中只有一个方法
public void run ( );  用以定义线程运行体。

使用 Runnable 接口可以为多个线程提供共享的数据。
在实现 Runnable 接口的类的 run 方法定义中可以使用 Thread 的静态方法:
public static Thread currentThread( ) 获取当前线程的引用

第二种

可以定义一个 Thread 的子类并重写其 run 方法如:
class MyThread extends Thread {
public void run( ){...}
}
然后生成该类的对象:
MyThread myThread = new MyThread(...)


例1:Runner1 r = new Runner1(); Thread t = new Thread(r);
两句如果换为 r.run( );就是先执行子线程的 run 方法,再执行主线程的 run 方法。
public class TestThread1 {
	public static void main(String[] args) {
		Runner1 r = new Runner1();
		Thread t = new Thread(r);
		t.start();//产生新分支,并交替运行
		for(int i =0; i<100;i++) {
			System.out.println("Main Thread:------"+i);
		}
	}
}

class Runner1 implements Runnable {//也可以直接继承Thread,但不推荐
	public void run() {
		for(int i = 0; i<100; i++) {
			System.out.println("Runner1 :"+i);
		}
	}
}



三、线程的状态转换






四、线程控制基本方法


例1:
import java.util.*;
public class TestInterrupt {
	public static void main(String[] args) {
		MyThread thread = new MyThread();
		thread.start();
		try {
			Thread.sleep(10000);//sleep在哪儿用,哪儿睡
		}catch(InterruptedException e) {
			thread.interrupt();
		}
		thread.interrupt();
	}
}




class MyThread extends Thread {
	public void run() {
		while(true) {
			System.out.println("==="+new Date()+"===");
			try {
				sleep(1000);
			}catch(InterruptedException e) {
				return;
			}
		}
	}
}


例2:Join合并线程
public class TestJoin {
	public static void main(String[] args) {
		MyThread2 t1 = new MyThread2("abcde");
		t1.start();
		try {
			t1.join();
		}catch(InterruptedException e) {}
		
		for(int i=1; i<=10; i++) {
			System.out.println("I am main thread!");
		}
	}
}

class MyThread2 extends Thread {
	MyThread2(String s) {
		super(s);
	}
	
	public void run() {
		for(int i=1; i<=10; i++) {
			System.out.println("I am " +getName());
			try {
				sleep(1000);
			}catch(InterruptedException e) {
				return;
			}
		}
	}
}


五、线程的优先级别

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。
线程的优先级用数字表示,范围从110,一个线程的缺省优先级是5.

 
public class TestPriority {
	public static void main(String[] args) {
		Thread t1 = new Thread(new T1());
		Thread t2 = new Thread(new T2());
		t1.setPriority(Thread.NORM_PRIORITY + 5);
		t1.start();
		t2.start();
	}
}

class T1 implements Runnable {
	public void run(){
		for(int i=0; i<300; i++) {
			System.out.println("T1: "+i);
		}
	}
}

class T2 implements Runnable {
	public void run(){
		for(int i=0; i<300; i++) {
			System.out.println("====T2:"+i);
		}
	}
}

六、线程同步

◆在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应在一个可称为”互斥锁”的标记,这个标记保证在任一时刻,只能有一个线程访问该对象。

关键字 synchronized 来与对象的互斥锁联系。当某个对象 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。
▶synchronized的使用方法如下面的Timer类,放在方法声明中表示整个方法为同步方法。


public class TestSync implements Runnable{
	Timer timer = new Timer();
	
	public static void main(String[] args) {
		TestSync test = new TestSync();
		Thread t1 = new Thread(test);
		Thread t2 = new Thread(test);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		t2.start();
	}
	public void run() {
		timer.add(Thread.currentThread().getName());
	}
}

class Timer {
	private static int num = 0;
	public synchronized void add(String name) {
		//synchronized(this) {//执行的过程中锁定当前对象
			num++;
			try {
				Thread.sleep(1);
			}catch(InterruptedException e) {}
			System.out.println(name + ", 你是第"+num+"个使用timer的线程");
		//}
	}
}


例2:死锁
public class TestDeadLock implements Runnable {
	public int flag = 1;
	static Object o1 = new Object();
	static 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();
	}
}



例3:面试题。另外一个线程是完全可以访问没有锁定的方法的。

public class TT implements Runnable{
	int b = 100;
	
	public synchronized void m1() throws Exception {
		b = 1000;
		Thread.sleep(5000);
		System.out.println("b =" + b);
	}
	
	public void m2() {
		System.out.println(b);
	}
	
	public void run() {
		try {
			m1();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		TT tt = new TT();
		Thread t = new Thread(tt);
		t.start();
		try {
			Thread.sleep(1000);
		}catch(Exception e){}
		
		tt.m2();
	}
}


例4.生产者消费者问题

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(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) {
		if(index == arrWT.length) {
			try {
				this.wait();
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
		arrWT[index] = wt;
		index ++;
	}
	
	public synchronized woTou pop(){
		if(index == 0) {
			try {
				this.wait();
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
		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++) {
			woTou wt = new woTou(i);
			ss.push(wt);
			System.out.println("生产了: "+ wt);
			try {
				Thread.sleep(1000);
			}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++) {
			woTou wt = ss.pop();
			System.out.println("消费了: "+ wt);
			try {
				Thread.sleep(1000);
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值