黑马程序员——多线程

------- android培训java培训、期待与您交流! ----------

 

多线程

1.      进程就是正在进行的程序

2.      线程是进程中的一个的一个独立的控制单元, ,线程控制着进程的执行

3.      一个进程中至少有一个进程, 多线程可以提高程序对CPU的利用

4.      Jvm在启动时启动了两个线程

a)        非守护线程, 就是main线程

b)        守护线程, 就是垃圾回收

在主方法运行期间, 堆内产生的垃圾同时被垃圾回收处理

5.      创建线程有种方式

a)        继承Thread

b)        声明类实现Runnable接口

创建线程的两种方式

1.      当前类继承Thread

步骤

a)      当前类继承Thread

b)      重写父类的run方法

c)      启动线程, 调用Thread类的start()

 

代码示例

class ThreadTest {
	public static void main(String[] args) {
		// 创建两个线程
		Test t1 = new Test("one.....");
		Test t2 = new Test("tow.....");
		// 启动两个线程
		t1.start();
		t2.start();

		// 主线程输出
		for (int i = 0; i < 100; i++) {
			System.out.println("main....." + i);
		}

	}
}

class Test extends Thread {
	// 构造方法将传入Threadname
	Test(String name) {
		super(name); // 这里给线程传入了一个名字
	}

	// 重写run
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + i);
		}
	}
}


 

2.      声明一个类实现Runnable接口

a)      声明一个类实现Runnable接口

b)      重写接口中的run方法

c)      启动线程, Runnable的实现类作为参数传给Thread对象

代码示例

class ThreadTest2 {
	public static void main(String[] args) {
		// 创建一个MyThread对象
		MyThread mt = new MyThread();
		// 创建两个线程
		Thread t1 = new Thread(mt);
		Thread t2 = new Thread(mt);
		t1.setName("one......");
		t2.setName("two......");
		// 启动线程
		t1.start();
		t2.start();

		for (int i = 0; i < 100; i++) {
			System.out.println("main......" + i);
		}
	}
}

class MyThread implements Runnable {

	// 重写run
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(Thread.currentThread().getName() + i);
		}

	}
}


 

线程中常使用的方法

1.      public void run()

如果创建一个线程一定要重写这个方法, 这个方法的内容就是在线程启动后执行的内容

2.      public void start()

这个方法是用来启动线程的

3.      public void setName(Stringname)

给当前线程设置一个名字

4.      public String getName()

返回该线程的名字, 一般结合Thread.currentTread()使用

5.      public static Thread currentThread

返回当前线程

6.      public static void sleep(longmillis)

可以使当前线程进入冻结状态, 在经过指定毫秒时间后或自动回到运行状态或临时堵塞状态

7.      其它方法

Interrupt()方法可以将当前冻结状态的线程唤醒, 进入运行状态

setPriority(int num) 设置线程的优先级, 最小是1, 最大是10

setDaemon(boolean b) 接收一个truefalse, 可以设置当前线程为守护线程或非守护线程, 守护线程在非守护线程结束后或自动结束

 

线程的状态

线程一共有5中状态

1.      创建, 创建线程的对象

2.      运行, 就是执行statrt方法

3.      冻结, 是线程遇到了sleepwait时由运行变成冻结, 当冻结状态结束后不一定回到运行状, 有可能回到临时堵塞状态

4.      临时堵塞, 当前线程具有执行资格, 但是没有执行权, 只能排等待cpu分配资源

5.      当线程执行结束会销毁

 

线程同步

1.      多线程安全问题

多线程程序, 多个线程操作共享数据

利用线程同步解决, 就是加锁

2.      锁的机制synchronized

a)      同步代码块

语法格式是 synchronized(锁对象) {代码}, 这里的锁可以是任意的对象

b)      同步方法

在方法声明的时候在返回值类型前面加上synchronized关键字, 持有的锁是当前对象

         注意: 类名.class也可以获得当前对象

3.      死锁

死锁就是两个线程相互持有对方的锁, A线程持有B线程的锁, B又持有A线程的锁, 两边都得不到释放, 从而造成死锁

 

代码示例

class DeadLockTest {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		Thread th1 = new Thread(mt);
		Thread th2 = new Thread(mt);

		th1.start();
		th2.start();
	}
}

class MyThread implements Runnable {

	Object obj = new Object(); // 创建一个锁对象
	boolean flag = true;

	public void run() {
		while (true) {
			if (flag) {
				synchronized (obj) { // obj同步
					flag = false;
					show2();
				}
			} else {
				flag = true;
				show1();
			}
		}

	}

	synchronized void show1() { // this锁同步
		synchronized (obj) { // obj锁同步
			System.out.println("obj lock .........");
		}
	}

	void show2() {
		synchronized (this) { // this锁同步
			System.out.println("this lock++++++++++");
		}
	}
}


 

线程通信

1.      线程通信是指在一个线程执行完毕后唤醒另一个线程执行, 实现线程之间逐一交替执行

2.      wait()方法是用来让当前线程进入等待状态

3.      notify方法时会随机唤醒一个等待的线程, 通常会使用一个flag标记来指定线程的执行权

4.      notifyAll()是唤醒等待中的所有线程

5.      以上这些方法都是在Object中定义的, 因为锁可以是任意对象, 所以在使用这些方法的时候一定要用所对象调用, 不然默认的是当前对象

代码示例

1)      两个线程交替执行

public class ThreadTest {
	public static void main(String[] args) {
		final MyCode mc = new MyCode();

		new Thread() {
			public void run() {
				while (true)
					try {
						mc.print1();
					} catch (InterruptedException e) {

					}
			}
		}.start();

		new Thread() {
			public void run() {
				while (true)
					try {
						mc.print2();
					} catch (InterruptedException e) {

					}
			}
		}.start();

	}

}

class MyCode {
	int flag = 1;
	Object obj = new Object();

	public void print1() throws InterruptedException {
		synchronized (obj) {
			if (flag != 1)
				obj.wait();
			System.out.print("传");
			System.out.print("智");
			System.out.print("播");
			System.out.print("客");
			System.out.print("\r\n");
			obj.notify();
			flag = 2;
		}
	}

	public void print2() throws InterruptedException {
		synchronized (obj) {
			if (flag != 2)
				obj.wait();
			System.out.print("黑");
			System.out.print("马");
			System.out.print("程");
			System.out.print("序");
			System.out.print("员");
			System.out.print("\r\n");
			obj.notify();
			flag = 1;
		}
	}
}


 

2)      多个线程交替执行

package cn.itcast.thread;

public class ThreadTest {
	public static void main(String[] args) {
		final MyCode mc = new MyCode();
		
		new Thread() {
			public void run() {
			while (true)
					try {
					mc.print1();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while (true)
					try {
					mc.print2();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while (true)
					try {
					mc.print3();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
	}

}

class MyCode  {
	int flag = 1;
	Object obj = new Object();
	public void print1() throws InterruptedException {
		synchronized(obj) {
			while (flag != 1)
				obj.wait();
			System.out.print("传");
			System.out.print("智");
			System.out.print("播");
			System.out.print("客");
			System.out.print("\r\n");
			obj.notifyAll();
			flag = 2;
		}
	}
	
	public void print2() throws InterruptedException {
		synchronized(obj) {
			while (flag != 2)
				obj.wait();
			System.out.print("黑");
			System.out.print("马");
			System.out.print("程");
			System.out.print("序");
			System.out.print("员");
			System.out.print("\r\n");
			obj.notifyAll();
			flag = 3;
		}
	}
	
	public void print3() throws InterruptedException {
		synchronized(obj) {
			while (flag != 3)
				obj.wait();
			System.out.print("C");
			System.out.print("S");
			System.out.print("D");
			System.out.print("N");
			System.out.print("\r\n");
			obj.notifyAll();
			flag = 1;
		}
	}
}


 

JDK5后同步线程

1.      Jdk5新加了Lock接口, 它的实现类ReentrantLock使同步线程和线程通信更加方便和高效

2.      ReentrantLock类中的方法

1)      public void lock()

这个方法可以获取锁, 相当于同步代码块中添加synchronized关键字

2)      public void unlock()

这个方法用来释放锁

3)      public Condition newCondition()

获得一个Condition的实例, Condition中提供了线程等待和唤醒线程的方法, 可以获得多个Condition, await()是线程等待的方法, signal()是唤醒一个等待线程, singnalAll()是唤醒所有等待中的线程, 同过Condition对象可以指定哪一个线程等待或是唤醒哪一个线程

 

代码示例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest {
	public static void main(String[] args) {
		final NewLock nl = new NewLock();
		
		//创建三个线程
		new Thread() {
			public void run() {
				while (true)
					try {
					nl.print1();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while (true)
					try {
					nl.print2();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while (true)
					try {
					nl.print3();
					} catch (InterruptedException e) {
						
					}
			}
		}.start();
		
	}

}

class NewLock  {
	int flag = 1;
	//创建一个锁对象
	ReentrantLock rl = new ReentrantLock();
	//创建三个Condition对象
	Condition c1 = rl.newCondition();	
	Condition c2 = rl.newCondition();
	Condition c3 = rl.newCondition();
	
	public void print1() throws InterruptedException {
		rl.lock();		//加锁
		if (flag != 1)
			c1.await();
		System.out.print("传");
		System.out.print("智");
		System.out.print("播");
		System.out.print("客");
		System.out.print("\r\n");
		flag = 2;
		c2.signal();	//唤醒c2
		rl.unlock();	//释放锁
		
	}
	
	public void print2() throws InterruptedException {
		rl.lock();
		if (flag != 2)
			c2.await();
		System.out.print("黑");
		System.out.print("马");
		System.out.print("程");
		System.out.print("序");
		System.out.print("员");
		System.out.print("\r\n");
		flag = 3;
		c3.signal();	//唤醒c3
		rl.unlock();
	}
	
	public void print3() throws InterruptedException {
		rl.lock();
		if (flag != 3)
			c3.await();
		System.out.print("C");
		System.out.print("S");
		System.out.print("D");
		System.out.print("N");
		System.out.print("\r\n");
		flag = 1;
		c1.signal();	//唤醒c1
		rl.unlock();
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值