/**
* 主程序类
* Java中的多线程
* 作者:Ai
* 时间:2018年4月28日18:31:49
*
*/
public class Program {
public static void main(String[] args){
// Lk.show(1,2,3,4);
//region 1.继承Thread类来实现多线程
//定义3个线程ABC
MyThread myThread=new MyThread("线程A");
MyThread myThread1=new MyThread("线程B");
MyThread myThread2=new MyThread("线程C");
//如果要想在程序之中真正的启动多线程,必须依靠Thread类的一个方法:public void start(),
// 表示真正启动多线程,调用此方法后会间接调用run()方法。
// myThread.start();
// myThread1.start();
// myThread2.start();
//注释:为啥不直接调用run方法呢?
//因为java要对线程的状态进行判断,对于一个已经启动的线程无法再次启动,这个判断线程状态的代码在各个平台上都是不同的
//所以java需要通过start()来启动线程,至于一些线程判断就交给JVM在不同平台进行适配
//endregion
//region 2.实现Runnable接口来实现多线程
MyThread2 myThread21=new MyThread2("线程AA");
MyThread2 myThread22=new MyThread2("线程BB");
MyThread2 myThread23=new MyThread2("线程CC");
//由于Runnable接口里并没有Start()[Start()方法在Thread类中]
//所以需要通过构造给Thread传递一个Runnable对象
//注释:Thread类同样实现了Runnable接口,感觉有点像是代理模式
// new Thread(myThread21).start();
// new Thread(myThread22).start();
// new Thread(myThread23).start();
//endregion
/**
* 注释:
*1.在实际开发中应当使用Runnable方式,可以避免单继承问题
*2.在多线程中只能操作当前正在运行的线程
*3.线程是依赖于进程的,在JVM启动时至少都会启动2个线程——main gc
* */
//region 3.线程优先级
//#创建一个线程(这里使用的是匿名内部类
Thread thread=new Thread(){
@Override
public void run() {
for (int i=0;i<50;i++){
System.out.println(this.getName()+" "+i);
if (i==25){
//#暂停当前正在执行的线程对象,并执行其他线程。(线程让步
Thread.yield();
}
}
//#获得当前正在执行的线程应用
Thread th=Thread.currentThread();
}
};
//#线程的优先级越高,越有可能先执行
//#设置线程名称
thread.setName("自定义线程A");
//发现设置和取得优先级的时候都是利用了一个int型数据的操作
//最高优先级:public static final int MAX_PRIORITY,10;
//中等优先级:public static final int NORM_PRIORITY,5;
//最低优先级:public static final int MIN_PRIORITY,1;
thread.setPriority(10);
//#开启线程
// thread.start();
//endregion
//region 4.线程常用方法
//我们先创建几个线程
MyThread thread1=new MyThread("线程01");
MyThread thread2=new MyThread("线程02");
MyThread thread3=new MyThread("线程03");
//#1.线程名称(如果不设置线程名称,会有默认的名称
thread1.setName("设置的线程01");
thread1.getName();
//#2.设置优先级
thread1.setPriority(1);
//#3.设置线程为用户线程
thread1.setDaemon(true);
//#4.中断线程
thread1.interrupt();
//#5.测试线程是否处于活动状态
thread1.isAlive();
//Thread类静态方法
//#1.线程让步
Thread.yield();
//#2.线程休眠(毫秒
// Thread.sleep(100);
//endregion
//region 5.线程的同步和死锁
//#1.通过synchronized(this){}代码块实现线程同步(资源共享)
//#2.通过synchronized关键字声明同步方法实现线程同步(资源共享)
//存入30块钱
Bank bank=new Bank(30);
//创建5个取款人同时取款(此时他们操作的都是同一个bank对象
new Thread(bank,"取款人A").start();
new Thread(bank,"取款人B").start();
new Thread(bank,"取款人C").start();
new Thread(bank,"取款人D").start();
new Thread(bank,"取款人E").start();
//同步就是指一个线程要等待另外一个线程执行完毕才会继续执行的一种操作形式,但是如果在一个操作之中都是在互相等着的话,那么就会出现死锁问题。
//endregion
}
}
//多线程的实现,实现多线程可以通过继承Thread类或实现Runnable接口来完成定义
/**
* 1.继承Thread来实现多线程
*/
class MyThread extends Thread{
private String title;
public MyThread(String title){
this.title=title;
}
//在线程启动时会自动调用该方法
@Override
public void run() {
for (int i=0;i<50;i++){
System.out.println(title+"运行,x="+i);
}
}
}
/**
* 2.通过实现Runnable接口来实现多线程
*
*由于单继承机制,在某些时候我们能够实现Runnable接口来实现多线程
*/
class MyThread2 implements Runnable{
private String title;
public MyThread2(String title){
this.title=title;
}
@Override
public void run() {
for (int i=0;i<50;i++){
System.out.println(title+"运行,Y="+i);
//进行线程休眠(需要进行异常捕获
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 银行类
*/
class Bank implements Runnable{
private int data;
public Bank(int data){
this.data=data;
}
@Override
public void run() {
// for (int x=0;x<10;x++){
//#synchronized代码块表示该代码块需要同步,每次只能由一条线程来访问他
// synchronized (this){
// if (data>0){
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// //取款
// System.out.println(Thread.currentThread().getName()+"取款,data="+data--);
// }
//#同步方法
for (int i=0;i<10;i++){
withdrawal(1);
}
}
/**
* 取款方法(同步方法)
* 添加synchronized关键字来声明同步方法
*/
private synchronized void withdrawal(int num){
if (data>0){
try {
Thread.sleep(1000);
data-=num;
System.out.println(Thread.currentThread().getName()+"同步取款,data="+data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}