---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------
1、为什么需要线程
线程给程序提供了不同的执行入口,也使得不同的程序可以同时在内存中运行,而不是一定要等一段代码执行完毕之后再执行下一段。这就是为什么需要线程。
2、线程的创建方式;
一种是继承Thread类,另一种是实现Runnable接口,一般使用第二种,因为java只支持单继承,而接口可以实现多个,这就使得类的功能更齐全。第二种创建方式基本都是如下:
new Thread(new XXClass).start(); (XXClass实现了Runnable接口)
3、线程使用中需要注意的问题:
a、同步
当两个线程或两个以上对同一资源进行操作时,就需要对线程进行同步,同步所用的锁必须是同一对象,否则会出现各种乱七八糟的问题,另外同步的代码块或者方法中尽量避免有无需同步的部分。
b、通信
当两个或两个以上线程对统一资源进行不同的操作,而这两种操作还有对立性,比方说一个做面包,一个吃面包,那就得有个机制来判断面包有没有的吃,吃没吃完了。这时候用的就是等待与唤醒机制,有三个方法用在此处:
wai(), notify(), notifyAll()
这些方法都是由锁对象调用,wai() 的作用是让当前持有锁的线程等待,notify()随机唤醒一个在锁的范围里等待的线程,notifyAll()则是唤醒所有;这里面要注意一点就是当有三个线程以上时,判断需不需要等待要用while()语句,唤醒都用notifyAll(),否则会出问题,比如线程全部等待(与死锁现象差不多),还有就是连着做同一个动作。
在JDK1.5以后Lock类使线程的操作更为明朗,更好理解,而且在Lock中可以定义不同的condition来控制线程的唤醒与等待,使其更有目标性,节省内存资源。
c、其他方法
join() 执行该方法语句所在的线程会等待调用该方法的对象线程结束,再与其他线程抢资源运行
interrupt() 将处于冻结状态的线程强制叫醒;被叫醒的线程会抛出一个InterrptedException 异常
setDaemon()将线程设置为守护线程,守护线程除了人为结束之外,会在该线程所在的线程组中所有的非守护线程都结束之后结束。
yield() 这个方法用的很少,就是使当前线程暂停一会,然后执行其他线程;就好像是跑累了坐下来休息一会,让别人跑过去就是了
下面这个代码完全理解了线程就差不多就可以拿来用了
package com.itheima;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 仓库类
* @author Administrator
*
*/
class Resource_1 {
private String name;
private int count = 1;
private boolean flag = false;//这个标记用来判断线程等待与否
private Lock lock = new ReentrantLock();//定义锁
private Condition con = lock.newCondition();//定义一个condition来控制唤醒与等待
/**
* 这个方法是制造仓库中的事物
* @param name
*/
public void set(String name) {
lock.lock();//锁上,锁关联的别的线程都稍等
try {
while (flag)//用while循环来判断线程是否等待
con.await();//线程等待
this.name = name + "--" + count++;
System.out.println(Thread.currentThread().getName() + "。。生产者。。"
+ this.name);
flag = true;//设置属性完毕后改变标签状态
con.signalAll();//叫醒锁关联的所有在等待的线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();//解锁,锁关联的其他线程有机会抢锁了
}
}
/**
* 这个方法用来消费仓库中的事物
* 代码参照制造部分
*/
public void show() {
lock.lock();
try {
while (!flag)
con.await();
System.out.println(Thread.currentThread().getName()
+ "。。consumer。。" + this.name);
flag = false;
con.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
/**
* 这个类就是调用仓库中制造事物方法的线程类了
* @author Administrator
*
*/
class Producer_2 implements Runnable {
private Resource_1 res;//定义仓库,确定操作的目标
/**
* 在创建实例对象的同时将仓库地址传进来
* @param res
*/
public Producer_2(Resource_1 res) {
this.res = res;
}
/**
* 开始制造事物了
*/
public void run() {
while (true) {
res.set("商品");
}
}
}
/**
* 消费线程
* @author Administrator
*
*/
class Consumer_2 implements Runnable {
private Resource_1 res;
public Consumer_2(Resource_1 res) {
this.res = res;
}
public void run() {
while (true) {
res.show();
}
}
}
/**
* 主线程
* @author Administrator
*
*/
public class ProducerConsumer_2 {
public static void main(String[] args) {
Resource_1 res = new Resource_1();//建立仓库
new Thread(new Producer_2(res)).start();
new Thread(new Consumer_2(res)).start();
new Thread(new Consumer_2(res)).start();
new Thread(new Producer_2(res)).start();
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net