计算机的CPU可以掌管多进程,JVM可以掌管多线程,一个应用程序就是一个进程,在其中又可以划分为多个线程,这些线程都可以获得CPU资源,而且轮流使用(不是绝对的轮流,而是在排队的所有线程中随机选择使用),JVM可以快速切换,使得像是多线程同步进行的假象,线程也是可以定义等级(1-10)十个等级,一般的默认是5,但是不提倡规定等级来使得算法正确执行。
线程的声明有两种方法:
1.定义Thread子类,并用子类声明线程对象,子类需要重写run()方法。
2.实现目标接口,implements Runnable,并且重写run()方法。声明的格式是Thread thread = new Thread(Runnable target);//target是实现了Runnable接口的实例
两者很类似,但是第二种比较常用,将要实现的具体功能都放在了接口中实现
线程的执行都是相同的,首先调用start()方法排队,然后系统会自动执行run()方法,在第一种声明方法中,run方法来自父类Thread,父类中的run是空的,需要重写,在第二种声明方法中,run方法来自接口Runnable,依然要重写。在没有执行完run()方法之前,不允许重新排队。
在主线程(main方法)中可以启动其他线程,其实在任何一个线程中都可以启动其他线程。
线程不都是在争夺资源的,有时候他们也会谦让一下,主动sleep()一下,让出CPU资源;别的线程也不好意思一直占用,也会谦让回去,调用interrupt()打断正在休眠的线程。
sleep是Thread类的静态方法,用类名调用,但是在睡眠过程中可能被吵醒,就放在try~catch中:
try{Thread.sleep(1000);//1000 ms
}catch(InterruptedException e){}
虽然线程好,但是也有麻烦事,看似很完美的一段代码,运行结果和想象的大相径庭,应为JVM在切换过程中不考虑run()是否执行完毕,等到下次在从中断处继续执行,简单来说就是JVM想从哪里切换就可以从哪里切换,但是有一个关键词是很好的synchronized(同步的),被这个关键词修饰的方法在没有执行完之前是不允许其他线程来捣乱的,这叫线程同步,如果我们需要一个线程完整的完成一些操作后,其他线程才可以进行这些操作,那么就可以把这些操作封装到一个synchronized方法中。
public class MainThread {
/**
使用Thread子类声明线程
*/
public static void main(String[] args) {
SpeakDog speakDog;
SpeakCat speakCat;
speakDog = new SpeakDog();
speakCat = new SpeakCat();
speakDog.start();
speakCat.start();
for(int i = 1; i <= 10; i++)
System.out.print("动物"+i+" ");
}
}
public class SpeakDog extends Thread{
public void run(){
for(int i = 1; i <= 10; i++)
System.out.print("小狗"+i+" ");
}
}
public class SpeakCat extends Thread{
public void run(){
for(int i = 1; i <= 10; i++){
System.out.print("小猫"+i+" ");
}
}
}
public class MainThread {
/**
interrupt
*/
public static void main(String[] args) {
Road road = new Road();
Thread police,driver;
police = new Thread(road);
driver = new Thread(road);
police.setName("警察");
driver.setName("司机");
road.setAttachThread(driver);
driver.start();
police.start();
}
}
public class Road implements Runnable{
Thread attachThread;
public void setAttachThread(Thread t){
attachThread = t;
}
public void run(){
String name = Thread.currentThread().getName();
if(name.equals("司机")){
System.out.println("我是"+name+",在马路上开车");
System.out.println("想睡一个小时再开车");
try{
Thread.sleep(1000*60*60);
}catch(InterruptedException e){
System.out.println("司机被警察叫醒了");
}
System.out.println("继续开车");
}
if(name.equals("警察")){
for(int i =0; i < 3; i++)
System.out.println(name+"喊:开车!");
try{
Thread.sleep(500);
}catch(InterruptedException e){}
attachThread.interrupt();//打断其他线程,没有在这里启动,但是是在这里打断的
}
}
}
我是司机,在马路上开车
警察喊:开车!
想睡一个小时再开车
警察喊:开车!
警察喊:开车!
司机被警察叫醒了
继续开车
public class MainThread {
/**
synchronized
*/
public static void main(String[] args) {
Bank bank = new Bank();
bank.setMoney(200);
Thread accountant,cashier;
accountant = new Thread(bank);
accountant.setName("会计");
cashier = new Thread(bank);
cashier.setName("出纳");
accountant.start();
cashier.start();
}
}
public class Bank implements Runnable{
int money;
public void setMoney(int m){
money = m;
}
public void run(){
if(Thread.currentThread().getName().equals("会计")){
SaveOrTake(300);
}else if(Thread.currentThread().getName().equals("出纳")){
SaveOrTake(150);
}
}
public synchronized void SaveOrTake(int t){
if(Thread.currentThread().getName().equals("会计")){
for(int i = 0; i < 3; i++){
money += t/3;
System.out.println(Thread.currentThread().getName()+"存入"+t/3+"万元,账上共有"+money+"万元");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
}
}
else if(Thread.currentThread().getName().equals("出纳")){
for(int i =0; i < 3; i++){
money -= t/3;
System.out.println(Thread.currentThread().getName()+"取出"+t/3+"万元,账上共有"+money+"万元");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
}
}
}
}
会计存入100万元,账上共有300万元
会计存入100万元,账上共有400万元
会计存入100万元,账上共有500万元
出纳取出50万元,账上共有450万元
出纳取出50万元,账上共有400万元
出纳取出50万元,账上共有350万元
public class MainThread {
/**
AntUpgrade && synchronized
*/
public static void main(String[] args) {
House house = new House();
house.setCake(10);
Thread antOne,antTwo;
antOne = new Thread(house);
antOne.setName("红蚂蚁");
antTwo = new Thread(house);
antTwo.setName("黑蚂蚁");
antOne.start();
antTwo.start();
}
}
public class House implements Runnable{
int cake;
public void setCake(int c){
cake = c;
}
public void run(){
while(true){
antDoing();
if(cake <= 0) return;
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
}
}
public synchronized void antDoing(){
String name = Thread.currentThread().getName();
int m = 2;
if(cake-m >= 0){
System.out.println(name+"吃掉了"+m+"克的蛋糕");
cake -= m;
System.out.println(name+"发现蛋糕还剩"+cake+"克");
}
else{
System.out.println(name+"发现没有蛋糕了,进入死亡");
}
}
}
红蚂蚁吃掉了2克的蛋糕
红蚂蚁发现蛋糕还剩8克
黑蚂蚁吃掉了2克的蛋糕
黑蚂蚁发现蛋糕还剩6克
红蚂蚁吃掉了2克的蛋糕
红蚂蚁发现蛋糕还剩4克
黑蚂蚁吃掉了2克的蛋糕
黑蚂蚁发现蛋糕还剩2克
红蚂蚁吃掉了2克的蛋糕
红蚂蚁发现蛋糕还剩0克
黑蚂蚁发现没有蛋糕了,进入死亡
未完待续。。