java多线程
java实现多线程的方式有两种:
继承Thread类,重写run方法
实现Runnable接口,并重写run方法
实现多线程的两种方式:
继承Thread:
/**
*
* @Description: 线程的实现方式之继承Thread类
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class TestThread {
public static void main(String[] args) {
new Thread(){
public void run() {
System.out.println("老公: 我犯错了,老婆让我说一百句 i love you");
System.out.println("************************************");
for(int i=0;i<100;i++){
System.out.println("第"+(i+1)+"句: i love you");
}
System.out.println("************************************");
System.out.println("老婆: 态度诚恳,就原谅你了");
}
}.start();
}
}
实现Runnable接口:
/**
*
* @Description: 线程的实现方式之实现Runnable接口
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class TestThread2 {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("老公: 我犯错了,老婆让我说一百句 i love you");
System.out.println("************************************");
for (int i = 0; i < 100; i++) {
System.out.println("第" + (i + 1) + "句: i love you");
}
System.out.println("************************************");
System.out.println("老婆: 态度诚恳,就原谅你了");
}
}).start();
}
}
/**
*
* @Description: 线程的实现方式
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class TestThread3 {
public static void main(String[] args) {
// 方式1:继承Thread的形式
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("你是谁啊?");
}
}
};
// 方式2:实现Runnable接口的形式
Runnable runn = new Runnable() {
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("我是修水管的");
}
}
};
Thread t2 = new Thread(runn);
t1.start();
t2.start();
}
}
线程相关API:
/**
*
* @Description: 线程相关的api
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadApiDemo {
public static void main(String[] args) {
// 查看main线程的相关信息
Thread t = Thread.currentThread();
long id = t.getId();
String name = t.getName();//setName();
int prioirty = t.getPriority();//setPriority();
System.out.println("id:" + id);
System.out.println("name:" + name);
System.out.println("priority:" + prioirty);
System.out.println("isAlive:" + t.isAlive());
System.out.println("isDaemon:" + t.isDaemon());//setDaemon();
System.out.println("isInterrupted:" + t.isInterrupted());
}
}
/**
*
* @Description: 线程优先级
* 理论上线程优先级越高的线程,被分配cpu时间片的次数就多
* 换句话说被执行的次数就多。
* 优先级1-10
* 10最大,1最小,默认情况下线程创建出来时优先级是5
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadPriorityDemo {
public static void main(String[] args) {
Thread max = new Thread(){
public void run(){
for(int i=0;i<1000;i++){
System.out.println("max");
}
}
};
Thread norm = new Thread(){
public void run(){
for(int i=0;i<1000;i++){
System.out.println("norm");
}
}
};
Thread min = new Thread(){
public void run(){
for(int i=0;i<1000;i++){
System.out.println("min");
}
}
};
max.setPriority(Thread.MAX_PRIORITY);
min.setPriority(Thread.MIN_PRIORITY);
min.start();
norm.start();
max.start();
}
}
/**
*
* @Description: 守护线程(后台线程)
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadDaemonDemo {
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:AAAAAAaaaaaa......");
System.out.println(
"旁白:噗通!");
}
};
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();
/*
* 设置为守护线程应该在start()方法之
* 前被调用
*/
jack.setDaemon(true);
jack.start();
}
}
CurrentThread:
/**
*
* @Description: 当前线程
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class CurrentThreadDemo {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println("运行main方法的线程是:" + t);
test();
// 自己创建的线程
Thread myT = new Thread() {
public void run() {
Thread tt = Thread.currentThread();
System.out.println("运行run方法的线程是:" + tt);
test();
}
};
myT.start();
}
public static void test() {
/*
* 获取运行Thread.currentThread()这个方法 的线程,并返回
*/
Thread t = Thread.currentThread();
System.out.println("运行currentThread方法的线程是" + t);
}
}
Join:
/**
*
* @Description: join方法可以让当前线程在某一个线程上等待,直到其
* 结束后,再让当前线程继续执行。
* join会引起线程阻塞
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadJoinDemo {
// 表示图片是否下载完毕了
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:准备显示图片...");
// 首先要等待下载线程将图片下载完毕
try {
/*
* 这里阻塞的是show线程,直到download 线程执行完毕后,join方法才会解除 阻塞
*/
download.join();
} catch (InterruptedException e) {
}
if (!isFinish) {
throw new RuntimeException("图片没有下载完毕!显示失败!");
}
System.out.println("show:已经显示图片");
}
};
download.start();
show.start();
}
}
/**
*
* @Description: join方法可以让当前线程在某一个线程上等待,直到其
* 结束后,再让当前线程继续执行。
* join会引起线程阻塞
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadJoinDemo2 {
public static void main(String[] args)throws Exception {
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:图片下载完毕!");
}
};
Thread show = new Thread() {
public void run() {
System.out.println("show:已经显示图片");
}
};
download.start();
download.join();
show.start();
show.join();
}
}
/**
*
* @Description: wait()与notify()方法是在Object上定义的方法
* 换句话说线程可以在任意对象上等待,在特殊情况下,wait,notity的性能高于
* join,join是需要等待线程执行完成,wait,notify 是可以在线程的任何位置
* (同步块中)
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class WaitAndNotityDemo {
private static boolean isFinish = false;
public static void main(String[] args) {
final Object obj = new Object();
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:准备显示图片...");
// 首先要等待下载线程将图片下载完毕
try {
synchronized (obj) {
obj.wait();
}
} catch (InterruptedException e) {
}
if (!isFinish) {
throw new RuntimeException("图片没有下载完毕!显示失败!");
}
System.out.println("show:已经显示图片");
}
};
download.start();
show.start();
}
}
线程的资源共享问题:
/**
*
* @Description: 线程之间资源共享的问题
* 非静态资源
* 静态资源(特性就是共享)
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class Table {
private int beans = 20;
/*
* 非静态方法中所的对象是:
* 线程调用哪个对象的getBean()方法,锁的就是哪个
* 对象,这个例子中锁的就是main方法中第一行创建的
* table对象。
*/
public synchronized int getBean(){
if(beans==0){
throw new RuntimeException("没有豆子了");
}
Thread.yield();
return beans--;
}
public static void main(String[] args) {
final Table table = new Table();
Thread t1 = new Thread(){
public void run(){
while(true){
int bean = table.getBean();
Thread.yield();
System.out.println(
getName()+":"+bean);
}
}
};
Thread t2 = new Thread(){
public void run(){
while(true){
int bean = table.getBean();
System.out.println(
getName()+":"+bean);
}
}
};
t1.start();
t2.start();
}
}
/**
*
* @Description: 线程之间资源共享的问题
* 非静态资源
* 静态资源(特性就是共享)
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class Table {
/*
* 静态方法中锁的对象是:
* 线程调用哪个对象的getBean()方法,锁的就是哪个
* 对象,这个例子中锁的就是main方法中第一行创建的
* table对象。
*/
static class Bean implements Runnable{
private static int beans = 20;
public synchronized int getBean(){
if(beans==0){
throw new RuntimeException("没有豆子了");
}
Thread.yield();
return beans--;
}
public void run() {
while(true){
int bean = getBean();
Thread.yield();
System.out.println(
Thread.currentThread().getName()+":"+bean);
}
}
}
public static void main(String[] args) {
final Bean bean=new Bean();
Thread t1 = new Thread(bean);
Thread t2 = new Thread(bean);
t1.start();
t2.start();
}
}
资源共享问题,最好是使用静态资源,实现Runnable接口
线程安全问题:
/**
*
* @Description: 多线程并发安全问题
* 多线程访问统一资源时就会产生并发安全问题
* 解决办法:将异步操作变为同步操作
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadSynchronizedDemo1 {
private static int beans = 20;
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
while (true) {
int bean = getBean();
System.out.println(getName() + ":" + bean);
}
}
};
Thread t2 = new Thread() {
public void run() {
while (true) {
int bean = getBean();
Thread.yield();
System.out.println(getName() + ":" + bean);
}
}
};
t1.start();
t2.start();
}
/*
* 静态方法上被声明synchronized后,该静态方法 变为同步,当线程执行该方法使,会把当前类对象锁住
* 因为一个类只有一个类对象,所以其他线程发现该类对象 被锁住后,该方法就进不去了。从而保证同一个方法不能 被多个线程同时访问内部。
* 不了解反射时,可能不清楚类对象,可以简单理解为将 静态方法所属的类加所,因为类Sync只有一个。
*/
public synchronized static int getBean() {
if (beans == 0) {
throw new RuntimeException("没豆子了");
}
Thread.yield();
return beans--;
}
}
/**
*
* @Description: 减小同步范围可以提高代码执行效率
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadSynchronizedDemo2 {
public static void main(String[] args) {
final ThreadSynchronizedDemo2 demo = new ThreadSynchronizedDemo2();
Thread t1 = new Thread(){
public void run(){
try {
demo.buy();
} catch (InterruptedException e) {
}
}
};
Thread t2 = new Thread(){
public void run(){
try {
demo.buy();
} catch (InterruptedException e) {
}
}
};
t1.start();
t2.start();
}
/*
* 买衣服
*/
public void buy() throws InterruptedException{
Thread t = Thread.currentThread();
System.out.println(t.getName()+"正在挑衣服...");
Thread.sleep(5000);
/*
* 同步块要求锁的对象多线程要看到的是同一个
* 才有效果。否则没意义。
* synchronized (new Object()) {
* 上面的写法就是个错误的!
*/
synchronized (this) {
System.out.println(t.getName()+"正在试衣服...");
Thread.sleep(5000);
}
System.out.println(t.getName()+"结账。");
}
}
/**
*
* @Description: synchronized又称为互斥锁
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月11日
* @version V1.0
*/
public class ThreadSynchronizedDemo3 {
public static void main(String[] args) {
final ThreadSynchronizedDemo3 demo = new ThreadSynchronizedDemo3();
Thread t1 = new Thread() {
public void run() {
demo.foo();
}
};
Thread t2 = new Thread() {
public void run() {
demo.boo();
}
};
t1.start();
t2.start();
}
public void foo() {
synchronized (this) {
System.out.println("foo start");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("foo end");
}
}
public void boo() {
synchronized (this) {
System.out.println("boo start");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("boo end");
}
}
}
线程池:
/**
*
* @Description: 线程池
* @author king-pan pwpw1218@msn.cn
* @date 2014年10月12日
* @version V1.0
*/
public class ExecutorServiceDemo {
public static void main(String[] args) {
/*
* 创建一个固定大小的线程池 线程数为2
*/
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
Runnable run = new Runnable() {
public void run() {
Thread t = Thread.currentThread();
System.out.println("运行当前任务的线程是:" + t);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(t + "运行完任务了!");
}
};
threadPool.execute(run);
}
}
}