JAVA API 线程(一)

本文是关于Java API中线程使用的初步介绍,通过示例深入解析如何创建和管理线程,重点探讨了`synchronized`关键字在多线程环境中的应用。
摘要由CSDN通过智能技术生成
<p> </p>
示例一:
/*
  * 线程:
  *     程序:
  *     进程:正在内存中运行的程序
  *     线程:进程中并发运行的的独立过程,是可以单独执行的过程。
  *     
  *     java将操作系统复杂的线程机制封装到了Thread类。
  *      java如何开启线程:
  *        1 继承Thread
  *        2 重写run提供独立运行的过程
  *        3 创建线程对象
  *        4 调用Thread提供start方法,将run提交给操作系统,由操作系统调度并执行
  *        5 操作系统独立的执行run方法
  * 当前线程:
  *    是被并发调用的,获取正在执行当前方法的线程,可以使用Thread.crrentThread()     
  */
/**
 * 线程的第一种创建方式:
 * 继承Thread类并重写run方法
 * @author Administrator
 *
 */
public class ThreadDemo1 {
	public static void main(String[] args) {
//		for(int i=0;i<1000;i++){
//			/*
//			 * 有先后顺序的执行称为同步的。
//			 */
//			System.out.println("你是谁啊?");
//			System.out.println("我是查水表的。");
//		}
		
		Thread t1 = new MyThread1();
		Thread t2 = new MyThread2();
		/*
		 * 启动线程调用的是线程的start方法,而不是run方法!
		 */
		t1.start();
		t2.start();
		
		
	}
}
/**
 * 继承线程,并重写run方法
 * @author Administrator
 *
 */
class MyThread1 extends Thread{
	/**
	 * run方法中用来定义当前线程要执行的任务
	 */
	public void run(){
		for(int i=0;i<1000;i++){
			System.out.println("你是谁啊?");
		}
	}
}

class MyThread2 extends Thread{
	/**
	 * run方法中用来定义当前线程要执行的任务
	 */
	public void run(){
		for(int i=0;i<1000;i++){
			System.out.println("我是查水表的。");
		}
	}
}
/**
 * 第二种创建线程的方式:
 * 实现Runnable接口,来单独定义任务。
 * 这种方式可以解决第一种创建方式的两个不足:
 * 1:直接继承Thread就不能再继承其他类
 * 2:线程与线程要执行的任务有强耦合关系
 * @author Administrator
 *
 */
public class ThreadDemo2 {
	public static void main(String[] args) {
		//创建线程要执行的任务
		Runnable runn1 = new MyRunnable1();
		Runnable runn2 = new MyRunnable2();
		
		/*
		 * 创建线程,同时指派任务
		 */
		Thread t1 = new Thread(runn1);
		Thread t2 = new Thread(runn2);
		
		t1.start();
		t2.start();
	}
}
/**
 * 实现Runnable接口,定义线程要执行的任务
 * @author Administrator
 *
 */
class MyRunnable1 implements Runnable{
	public void run() {
		for(int i=0;i<1000;i++){
			System.out.println("你是谁啊?");
		}		
	}	
}

class MyRunnable2 implements Runnable{
	public void run() {
		for(int i=0;i<1000;i++){
			System.out.println("我是查水表的。");
		}		
	}	
}

/**
 * 使用匿名内部类方式创建线程
 * @author Administrator
 *
 */
public class ThreadDemo3 {
	public static void main(String[] args) {
		//方式1
		Thread t1 = new Thread(){
			public void run(){
				for(int i=0;i<1000;i++){
					System.out.println("你是谁啊?");
				}
			}
		};
		
		//方式2
		Runnable runn = new Runnable(){
			public void run(){
				for(int i=0;i<1000;i++){
					System.out.println("我是查水表的。");
				}
			}
		};
		Thread t2 = new Thread(runn);
		
		t1.start();
		t2.start();
		
	}
}

/**
 * 
 * 11716818  名字 职务 校区
 * 
 * Thread的静态方法currentThread()
 * 用来获取运行当前方法的线程
 * @author Administrator
 *
 */
public class ThreadDemo4 {
	public static Thread main;
	public static void main(String[] args) {
		/*
		 * 获取运行main方法的线程
		 */
		main = Thread.currentThread();
		System.out.println(main);		
		dosome();
		
		//自定义线程
		Thread myThread = new Thread(){
			public void run(){
				Thread t = Thread.currentThread();
				System.out.println("自定义线程:"+t);
				dosome();
			}
		};
		myThread.start();
	}
	
	public static void dosome(){
		Thread t = Thread.currentThread();
		if(t!=main){
			System.out.println("不是main线程,不能执行该方法");
			return;
		}
		
		System.out.println("运行dosome方法的线程是:"+t);
	}
}

/**
 * 获取线程相关信息的API
 * @author Administrator
 *
 */
public class ThreadDemo5 {
	public static void main(String[] args) {
		//获取运行main方法的线程
		Thread t = Thread.currentThread();
		
		//获取id(唯一标示符)
		System.out.println("id:"+t.getId());
		
		//获取线程名字
		System.out.println("name:"+t.getName());
		
		//获取优先级
		System.out.println("priority:"+t.getPriority());
		
		//是否活动
		System.out.println("isAlive:"+t.isAlive());
		
		//是否为守护线程
		System.out.println("isDaemon:"+t.isDaemon());
		
		//是否被中断
		System.out.println("isInterrupted:"+t.isInterrupted());
		
	}
}

/**
 * 线程优先级
 * 由于线程切换由线程调度负责,线程本身无权干涉,所以
 * 我们可以通过改变线程的优先级来最大程度影响时间片的
 * 分配。
 * 线程优先级分为10个等级。1-10.
 * 10最高,1最低
 * 线程定义了三个常量:
 * MAX_PRIORITY:10 表示最高优先级
 * MIN_PRIORITY: 1  表示最低优先级
 * NORM_PRIORITY:5  表示默认优先级
 * 创建出来的线程默认优先级都是:5
 * 
 * 理论上优先级高的线程,被分配时间片的次数就多
 * 
 * @author Administrator
 *
 */
public class ThreadDemo6 {
	public static void main(String[] args) {
		Thread max = new Thread(){
			public void run(){
				for(int i=0;i<10000;i++){
					System.out.println("max");
				}
			}
		};
		Thread min = new Thread(){
			public void run(){
				for(int i=0;i<10000;i++){
					System.out.println("min");
				}
			}
		};
		Thread norm = new Thread(){
			public void run(){
				for(int i=0;i<10000;i++){
					System.out.println("norm");
				}
			}
		};
		//设置线程的优先级
		min.setPriority(Thread.MIN_PRIORITY);
		max.setPriority(Thread.MAX_PRIORITY);
		
		min.start();
		norm.start();
		max.start();
				
	}
}

/**
 * 守护线程
 * 当一个进程中所有前台线程都结束时,进程结束。无论进程
 * 中是否还有守护(后台)线程运行,都要被中断。
 * @author Administrator
 *
 */
public class ThreadDemo7 {
	public static void main(String[] args) {
		/*
		 * rose:扮演者,前台线程
		 */
		Thread rose = new Thread(){
			public void run(){
				for(int i=0;i<10;i++){
					System.out.println("rose:let me go!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
				System.out.println(
					"rose:啊啊啊啊啊AAAAaaaaaa....."
				);
				System.out.println("音效:噗通!");
			}
		};
		/*
		 * jack:扮演者,后台线程
		 */
		Thread jack = new Thread(){
			public void run(){
				while(true){
					System.out.println("jack:you jump!i jump!");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
				}
			}
		};
		
		rose.start();
		
		//设置为后台线程,注意,在启动线程前设置!
		jack.setDaemon(true);
		jack.start();
		
	}
}

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * static void sleep(long ms)
 * 使运行sleep方法的线程阻塞指定毫秒
 * 由于结束阻塞后线程处于Runnable状态而非Running,所以
 * 当解除阻塞后要再次等待线程调服分配时间片。这里的等待
 * 过程是误差。所以不能用该方法做精确的间隔操作。
 * @author Administrator
 *
 */
public class ThreadDemo8 {
	public static void main(String[] args) {
		/*
		 *	每秒钟输出一次当前系统时间,格式:HH:mm:ss
		 *  1:创建一个SimpleDateFormat指定时间格式
		 *  2:循环以下操作
		 *  3:创建一个Date实例,表示当前系统时间
		 *  4:使用SimpleDateFormat将Date转换为字符串
		 *  5:将字符串输出到控制台
		 *  6:使用Thread.sleep(1000)来阻塞一秒中
		 */
		SimpleDateFormat sdf 
			= new SimpleDateFormat("HH:mm:ss");	
		while(true){
			Date now = new Date();
			String str = sdf.format(now);
			System.out.println(str);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
	}
}	

/**
 * void join()
 * 是当前线程进入阻塞状态,等待另一个线程工作完毕,才解除
 * 阻塞。
 * 通常是用来解决两个线程配合完成工作的情况。是多个线程
 * 出现类似同步的效果。
 * @author Administrator
 *
 */
public class ThreadDemo9 {
	//该属性用于表示图片是否下载完毕
	private static boolean isFinish = false;
	
	public static void main(String[] args) {
		//下载线程
		final Thread download = new Thread(){
			public void run(){
				System.out.println("down:开始下载图片...");
				for(int i=1;i<=100;i++){
					System.out.println("down:已下载"+i+"%");
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("down:图片下载完毕!");
				isFinish = true;
			}
		};
		
		//显示图片的线程
		Thread show = new Thread(){
			public void run(){
				System.out.println("show:开始显示图片...");
				//先等待下载线程把图片下载完毕
				/*
				 * 一个方法中的局部内部类中若想引用该方法的其他
				 * 局部变量,那么该变量必须是final的。
				 */
				try {
					download.join();
				} catch (InterruptedException e) {
				}
				if(!isFinish){
					throw new RuntimeException("图片没有找到!");
				}
				System.out.println("show:显示图片成功!");
			}
		};
		
		
		download.start();
		show.start();
		
	}
}

示例二:

/**
 * 当多个线程同时操作同一数据时,由于线程切换的不确定性
 * 可能会导致逻辑出现混乱,对程序产生破坏。
 * 这就是我们常说的多线程并发安全问题。
 * @author Administrator
 *
 */
public class SyncDemo {
	public static void main(String[] args) {
		final Table table = new Table();
		Thread p1 = new Thread(){
			public void run(){
				while(true){
					int bean = table.getBean();
					System.out.println(getName()+":"+bean);
				}
			}
		};
		Thread p2 = new Thread(){
			public void run(){
				while(true){
					int bean = table.getBean();
					Thread.yield();
					System.out.println(getName()+":"+bean);
				}
			}
		};
		p1.start();
		p2.start();
	}
}

class Table{
	//桌子上有20个豆子
	private int beans = 20;
	/**
	 * 从桌子上获取一个豆子
	 * @return
	 */
	public synchronized int getBean(){
		if(beans==0){
			throw new RuntimeException("没有豆子了!");
		}
		Thread.yield();
		return beans--;
	}
}

/**
 * 使用synchronized块,有效的缩小同步范围,可以在保证
 * 线程安全的前提下提高多线程并发的效率
 * @author Administrator
 *
 */
public class SyncDemo2 {
	public static void main(String[] args) {
		//两个线程访问同一个商店
		final Shop shop = new Shop();
		Thread p1 = new Thread(){
			public void run(){
				shop.buy();
			}
		};
		Thread p2 = new Thread(){
			public void run(){
				shop.buy();
			}
		};
		p1.start();
		p2.start();
	}
	
}

class Shop{
	/**
	 * 买衣服逻辑
	 * 
	 * 若给方法加上synchronized后,那么锁的对象
	 * 就是当前方法所属的对象,就是this
	 * public synchronized void buy(){
	 * 	...
	 * }
	 * 
	 */
	public void buy(){
		Thread t = Thread.currentThread();
		try{
			System.out.println(t.getName()+"正在挑衣服...");
			Thread.sleep(5000);
			/*
			 * 使用同步块可以缩小同步范围,提高并发效率。
			 * 需要注意的是,同步监视器(同步对象)可以是
			 * 任何类型的对象,但是要保证多个线程看到的
			 * 是同一个在可以!
			 * 通常使用this就可以了
			 */	
			synchronized (this) {
				System.out.println(t.getName()+"正在试衣服...");
				Thread.sleep(5000);
			}	
			System.out.println(t.getName()+"结账离开。");
			
		}catch(Exception e){
		}
		
	}
}

/**
 * synchronized又叫做互斥锁
 * 若两段代码的锁对象一致,那么这两段代码是互斥的。
 * 不能同时执行。
 * @author Administrator
 *
 */
public class SyncDemo3 {
	public static void main(String[] args) {
		final Foo foo = new Foo();
		Thread t1 = new Thread(){
			public void run(){
				foo.a();
			}
		};
		Thread t2 = new Thread(){
			public void run(){
				foo.b();
			}
		};
		
		t1.start();
		t2.start();
	}
}

class Foo{
	public synchronized void a(){
		try{
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在调用a方法");
			Thread.sleep(10000);
			System.out.println(t.getName()+"执行完a方法了");
		}catch(Exception e){
		}
	}
	
	public synchronized void b(){
		try{
			Thread t = Thread.currentThread();
			System.out.println(t.getName()+":正在调用b方法");
			Thread.sleep(10000);
			System.out.println(t.getName()+"执行完b方法了");
		}catch(Exception e){
		}
	}
	
}


/**
 * wait与notify方法
 * 
 * @author Administrator
 *
 */
public class WaitAndNotifyDemo {
	//该属性用于表示图片是否下载完毕
	private static boolean isFinish = false;
	
	private static Object obj = new Object();
	
	public static void main(String[] args) {
		//下载线程
		final Thread download = new Thread(){
			public void run(){
				System.out.println("down:开始下载图片...");
				for(int i=1;i<=100;i++){
					System.out.println("down:已下载"+i+"%");
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("down:图片下载完毕!");
				isFinish = true;	
				//当图片下载完毕后,显示线程就可以工作了!
				
				synchronized (obj) {
					obj.notify();
				}
				
				
				System.out.println("down:开始下载附件...");
				for(int i=1;i<=100;i++){
					System.out.println("down:已下载"+i+"%");
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
					}
				}
				System.out.println("down:附件下载完毕!");
				
				
			}
		};
		
		//显示图片的线程
		Thread show = new Thread(){
			public void run(){
				System.out.println("show:开始显示图片...");
				//先等待下载线程把图片下载完毕
				/*
				 * 一个方法中的局部内部类中若想引用该方法的其他
				 * 局部变量,那么该变量必须是final的。
				 */
				try {
					/*
					 * 要求:调用哪个对象的wait方法,就要将哪个对象
					 * 加锁
					 */
					synchronized (obj) {
						obj.wait();
					}				
				} catch (InterruptedException e) {
				}
				if(!isFinish){
					throw new RuntimeException("图片没有找到!");
				}
				System.out.println("show:显示图片成功!");
			}
		};
		
		
		download.start();
		show.start();
		
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值