当前位置:文档之家› 马士兵_JAVA视频教程-第09章_多线程

马士兵_JAVA视频教程-第09章_多线程

马士兵_JAVA视频教程-第09章_多线程
马士兵_JAVA视频教程-第09章_多线程

第九章Java多线程机制

每个进程都有独立的代码和数据空间,进程间的切换会有很大开销。

线程可以看成轻量级的进程同一类线程共享代码和数据空间,每个线程有独立的运行栈个程序计数器,线程切换开销小。

多线程:在操作系统中能同时运行多个任务(程序)。

多线程:在同一个应用程序中有多个顺序流同时执行。

二、

说明:

Runnable接口https://www.doczj.com/doc/7014957072.html,ng.Runnable

–Java多线程机制的一个重要部分,实际上它只有一个run()方法

–Thread类实现了Runnable接口,相对于Thread类,它更适合于多个线程处理同一资源

–实现Runnable接口的类的对象可以用来创建线程,这时start方法启动此线程就会在此线程上运行run()方法

–在编写复杂程序时相关的类可能已经继承了某个基类,而Java不支持多继承,在这种情况下,便需要通过实现Runnable接口来生成多线程

Thread类https://www.doczj.com/doc/7014957072.html,ng.Thread

–在Java程序中创建多线程的方法之一是继承Thread类

–封装了Java程序中一个线程对象需要拥有的属性和方法

–从Thread类派生一个子类,并创建这个子类的对象,就可以产生一个新的线程。这个子类应该重写Thread 类的run方法,在run方法中写入需要在新线程中执行的语句段。这个子类的对象需要调用start方法来启动,新线程将自动进入run方法。原线程将同时继续往下执行

–Thread类直接继承了Object类,并实现了Runnable接口。它位于https://www.doczj.com/doc/7014957072.html,ng包中,因而程序开头不用import 任何包就可直接使用

例子:Thread\TestThread1.java 开始使用Eclipse

2 一般程序先执行子线程,再执行主线程(方法调用)

package Thread;

public class TestThread1_1 {

public static void main(String args[]) {

Runner1 r = new Runner1();

r.run();

for(int i=0; i<100; i++) {

System.out.println("Main Thread:------" + i);

}

}

}

class Runner1 implements Runnable {

public void run() {

for(int i=0; i<100; i++) {

System.out.println("Runner1 :" + i);

}

}

}

3继承Thread类(继承,不常用)

package Thread;

public class TestThread1_2{

public static void main(String arg[]){

Runner1_2 r = new Runner1_2();

r.start();

for (int i = 0 ;i <= 100; i++){

System.out.println("Main Thread:!!!!"+i);

}

}

}

class Runner1_2 extends Thread{

public void run(){

for (int i = 0 ;i <= 100; i++){

System.out.println("Runner2:!!!!"+i);

}

}

}

2010-4-2 21:04:16 – 2010-4-14 16:28:59

三、线程状态转换

四、线程控制基本方法

Sleep/Join/Yield方法Sleep/Join(需要捕获异常)

例子1 Thread/TestInterrupt.Java (线程结束的方式)

package Thread;

import java.util.*;

public class TestInterrupt {

public static void main(String arg[]){

MyThread thread = new MyThread();

thread.start();

try{Thread.sleep(10000);}//主线程睡眠…

catch(InterruptedException e){}

thread.interrupt();//中断线程。

}

}

class MyThread extends Thread{

boolean flag = true;

public void run(){//重写的方法不能抛出不必被重写方法不同的方法,此处不能写throws InterruptedException

while(flag){

System.out.println("----"+ new Date()+"----");

try{

sleep(1000);

}

catch(InterruptedException e){//捕获抛出的异常

return;//停止

}

}

}

}

例子2 Thread/TestJoin.Java (线程合并方式)

package Thread;

public class TestJoin {

public static void main(String[] args) {

MyThread2 t1 = new MyThread2("abcde");

t1.start();//启动分支线程

try {

t1.join();//把T1分支线程合并到当前线程

} 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;

}

}

}

}

例子3 Thread/TestYield.Java (让出Cup)

package Thread;

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();

}

}

}

}

五、线程优先级Priority

例子Thread/TestPriority.Java

package Thread;

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 + 3);//提高优先级

t1.start();

t2.start();

}

}

class T1 implements Runnable {

public void run() {

for(int i=0; i<1000; i++) {

System.out.println("T1: " + i);

}

}

}

class T2 implements Runnable {

public void run() {

for(int i=0; i<1000; i++) {

System.out.println("------T2: " + i);

}

}

}

2010年4月14日21:40:41 – 2010-4-15 16:23:44

六、例子TestThread2-6

TestThread2一个线程类可以启动两个线程

package Thread;

public class TestThread2 {//一个线程类可以启动两个线程public static void main(String args[]) {

Runner2 r = new Runner2();

Thread t1 = new Thread(r);

Thread t2 = new Thread(r);

t1.start();

t2.start();

}

}

class Runner2 implements Runnable {

public void run() {

for(int i=0; i<30; i++) {

System.out.println("No. " + i);

}

}

}

package Thread;

public class TestThread6 {

public static void main(String args[]){

Thread t = new Runner6();

t.start();

for(int i=0; i<50; i++) {

System.out.println("MainThread: " + i);

}

}

}

class Runner6 extends Thread {

public void run() {

System.out.println(Thread.currentThread().isAlive());

for(int i=0;i<50;i++) {

System.out.println("SubThread: " + i);

}

}

}

七、线程同步

引入:两人同时取同一账户的钱两个线程访问同一资源,进程之间协调的问题

解决:在进程访问独占资源时先锁定再访问synchronized 最好只锁定一个对象

package Thread;

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 void add(String name){

//public synchronized void add(String name){ //synchronized "锁定"关键字

//synchronized (this) {//锁定

num ++;

try {Thread.sleep (1);} //让线程睡眠,给另一个线程执行的机会,更容易看到xia catch (InterruptedException e) {}

System.out .println(name+", 你是第"+num +"个使用timer 的线程");

//}

}

}

t2, 你是第2个使用timer 的线程

t1, 你是第2个使用timer 的线程

问题出现在线程执行方法时被另一个线程打断了.

死锁

07_线程同步_3.avi

Thread/TestDeadLock.java

两个线程锁定了互斥的对象

package Thread;

//一个线程类模拟两个线程。用flag 区分

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) {

//锁定o1

try { Thread.sleep (500);

} catch (Exception e) {

e.printStackTrace();

}

synchronized(o2) {//锁定o2

System.out.println("1");

}

}

}

if(flag == 0) {

synchronized(o2) {//锁定o2

try {

Thread.sleep(500);

} catch (Exception e) {

e.printStackTrace();

}

synchronized(o1) {//锁定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();

}

}

一道面试题:08_线程同步_4.Avi.当m1()方法执行的过程中,另外的线程能执行m2()

八、生产者消费者问题11_线程同步_7_生产者消费者问题.avi XXX.wait() 让当前访问这个线程等待,此时这个线程的锁不存在了XXXX.notify() 唤醒在此对象监视器上等待的单个线程。

一个wait()对应一个notify()

package Thread;

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++) {

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++) {

WoTou wt = ss.pop();

System.out.println("消费了: " + wt);

try {

Thread.sleep((int)(Math.random() * 1000));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

Wait和Sleep区别

Wait时别的线程可以访问锁定的对象(调用wait方法的时候必须锁定该对象)

Sleep时别的线程不可以访问锁定对象。

sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

相关主题
文本预览
相关文档 最新文档