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