//线程同步练习
public class ThreadNoSynchronized {
public static void main(String argv[ ]){
ShareData oShare = new ShareData();//创建,初始化 ShareData 对象 oShare
ThreadDemo th1 = new ThreadDemo("Thread1",oShare);//创建线程 th1
ThreadDemo th2 = new ThreadDemo("Thread2",oShare);//创建线程 th2
th1.start();//启动线程 th1
th2.start();//启动线程 th2
}
}
class ShareData{
public static String szData = "";//声明,并初始化字符串数据域,作为共享数据
}
class ThreadDemo extends Thread{
private ShareData oShare;//声明,并初始化 ShareData 数据域
ThreadDemo(){}//声明,并实现 ThreadDemo 构造方法
//声明,并实现 ThreadDemo 带参数的构造方法
ThreadDemo(String szName,ShareData oShare){
super(szName);//调用父类的构造方法
this.oShare = oShare;//初始化 oShare 域
}
@SuppressWarnings("static-access")
public void run(){
//synchronized (oShare) { //加上本行代码,实现线程同步,线程有序执行
//不加上面代码为线程异步,会出现“线程赛跑”现象
for (int i = 0; i < 5; i++){
if (this.getName().equals("Thread1")){
oShare.szData = "这是第 1 个线程";
//为了演示产生的问题,这里设置一次睡眠
try{
Thread.sleep((int)Math.random() * 100);//休眠
}
catch(InterruptedException e){//捕获异常
e.printStackTrace();
}
System.out.println(this.getName() + ":" + oShare.szData); //输出字符串信息
}else if(this.getName().equals("Thread2")){
oShare.szData = "这是第 2 个线程";
//为了演示产生的问题,这里设置一次睡眠
try{
Thread.sleep((int)Math.random() * 100); //线程休眠
}catch(InterruptedException e){//捕获异常
e.printStackTrace();
}
System.out.println(this.getName() + ":" + oShare.szData); //输出字符串信息
}
}
//}
}
}
//线程优先级练习
public class ThreadPriority{
public static void main(String args[ ]){
//用 Thread 类的子类创建线程
InheritThread itd=new InheritThread();
//用 Runnable 接口类的对象创建线程
Thread rtd=new Thread(new RunnableThread());
itd.setPriority(5);//设置 myThread1 的优先级 5
rtd.setPriority(5);//设置 myThread2 的优先级 5
itd.start();//启动线程 itd
rtd.start();//启动线程 rtd
}
}
//设置线程优先级
class InheritThread extends Thread {
//自定义线程的 run()方法
public void run(){
System.out.println("我是InheritThread");//输出字符串信息
for(int i=0;i<10;i++){
System.out.println(" InheritThread: i="+i);//输出信息
try{
Thread.sleep((int)Math.random()*1000); //线程休眠,休眠时间为1000内的随机数
}
catch(InterruptedException e)//捕获异常
{}
}
}
}
//通过 Runnable 接口创建的另外一个线程
class RunnableThread implements Runnable{
//自定义线程的 run()方法
public void run(){
System.out.println("我是RunnableThread");//输出字符串信息
for(int i=0;i<10;i++){
System.out.println("RunnableThread : i="+i);//输出 i
try{
Thread.sleep((int)Math.random()*1000);//线程休眠,休眠时间为1000内的随机数
}
catch(InterruptedException e){//捕获异常
}
}
}
}
/*
多线程之间通信
本例子 模拟了生产者和消费者的关系。开始消费者调用消费方法时处于等待状
态,此时唤起生产者线程。生产者开始生产共享数据之后,消费者进行消费,但是当共享数
据为空,所有消费者必须等待,生产者继续生产,然后消费者再次消费,如此循环直到程序
运行最后,可以看到线程一直等待。注意这个线程进入等待后没有其他线程唤醒,除非强行
退出 JVM 环境,否则它一直等待。
注意:考虑到程序的安全性,多数情况下使用 notifiAll(),除非明确可以知道唤醒哪一个
线程。wait 方法调用的前提条件是当前线程获取了这个对象的锁,也就是说 wait 方法必须放
在同步块或同步方法中。
*/
public class ThreadCommunication{
public static void main(String[ ] args){
Queue q = new Queue(); //创建,并初始化一个队列
Producer p = new Producer(q); //创建,并初始化一个生产者
Consumer c = new Consumer(q); //创建,并初始化一个消费者
c.start(); //消费者线程启动
p.start(); //生产者线程启动
}
}
//生产者消费者线程
class Producer extends Thread{//实现生产者线程
Queue q;//声明队列 q
Producer(Queue q){ //生产者构造方法
this.q = q; //队列 q 初始化
}
public void run(){
for(int i=1;i<5;i++){ //循环添加元素
q.put(i); //给队列中添加新的元素
}
}
}
class Consumer extends Thread{
Queue q; //声明队列 q
Consumer(Queue q){ //消费者构造方法
this.q = q; //队列 q 初始化
}
public void run(){
while(true){ //循环消费元素
q.get(); //获取队列中的元素
}
}
}
class Queue{
int value = 0;//声明,并初始化整数类型数据域 value
boolean isEmpty = true;//声明,并初始化布尔类型数据域 isEmpty,用于判断队列的状态
//生产者生产方法
public synchronized void put(int v){
//如果共享数据没有被消费,则生产者等待
if (!isEmpty){
try{
System.out.println("生产者等待");
wait();//进入等待状态
}
catch(Exception e){//捕获异常
e.printStackTrace();//异常信息输出
}
}
value += v;//value 值加 v
isEmpty = false;//isEmpty 赋值为 false
System.out.println("生产者共生产数量:"+v);//输出字符串信息
notify();//生产之后通知消费者消费
}
//消费者消费的方法
public synchronized int get(){
//消费者消费前,如果共享数据已经被消费完,则消费者等待
if (isEmpty){
try{
System.out.println("消费者等待");//输出字符串信息
wait();//进入等待状态
}
catch(Exception e){//捕获异常
e.printStackTrace();//异常信息输出
}
}
value--;//value 值-1
if (value < 1){
isEmpty = true;//isEmpty 赋值 true
}
System.out.println("消费者消费一个,剩余:"+value);//输出信息
notify();//消费者消费后,通知生产者生产
return value;//返回 value
}
}