线程的五大状态
Java中的thread类自带有线程的一些方法,这些方法可以让线程睡眠,插队,提高线程调度的优先级等等,它们提供了改变线程状态的操作手段。(不过在JDK帮助文档中,一些方法已经不推荐使用)
线程方法中的一些有趣的地方
public class ttp { public static void main(String[] args) { //主线程的默认优先级 System.out.println(Thread.currentThread().getName()+"--->" + Thread.currentThread().getPriority()); MyPriorty mm = new MyPriorty(); Thread t1 = new Thread(mm); Thread t2 = new Thread(mm); Thread t3 = new Thread(mm); t1.setPriority(10); t1.start(); t2.setPriority(4); t2.start(); t3.setPriority(6); t3.start(); } } //Runnable接口实现接口,run方法为打印线程名称和线程的优先级 class MyPriorty implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"--->" + Thread.currentThread().getPriority()); } } //这里的输出有多种结果,因为优先级只是增加了线程被调度运行的机率
用户线程和守护线程。守护线程的作用是保证用户线程的执行过程正常,例如Java中的内存回收线程和后台记录操作日志等等,这些都是守护线程。虚拟机必须等待用户线程执行完毕,不用等待守护线程执行完毕。当用户线程完成后,虚拟机就自动关闭,守护线程也就自动死亡了。
//Java的Thread类自带设置守护线程的方法 Thread.setdaemon(true) //设置为守护线程 //一般我们创建的线程默认都是用户线程
线程同步。线程同步是出现多个线程访问同一个对象并都想对其进行操作的时候必须考虑的问题。不进行线程同步(并发)控制的多线程是不安全的。
//线程不安全,出现了-1张票以及有两个线程拿到同一张票的错误,所以这是一个不安全的线程 public class test05 { public static void main(String[] args) { buyTicket b1 = new buyTicket(); Thread t1 = new Thread(b1,"you"); Thread t2 = new Thread(b1,"i"); Thread t3 = new Thread(b1,"he"); Thread t4 = new Thread(b1,"she"); t1.start(); t2.start(); t3.start(); t4.start(); } } class buyTicket implements Runnable{ //剩余票数 private int ticketNums = 12; private boolean flag = true; @Override public void run() { while(flag){ buy(); } } private void buy(){ if(ticketNums <= 0){ flag = false; return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "买到了第" + ticketNums-- + "张票"); } }
线程同步实质上是一个等待机制。线程同步时会将多个线程放入对象等待池中进行排队(队列),等待前一个线程执行操作完毕,再有下一个线程进行执行操作。每个对象都有一个独有的锁(排他锁),每个线程执行时都会获得对象的排他锁,这样只有获得锁的线程可以对对象进行操作,执行结束后排他锁被下一个线程获得。总结来说,线程同步的形成条件就是:队列+锁。
在访问时加入锁机制synchronized,当一个线程获得对象得排他锁,独占资源,其他线程必须等待,使用后释放锁即可
线程同步也有一些存在的问题(大部分是以牺牲性能以保证安全)
一般来说,synchronized是方法声明中添加,默认对方法中的this对象资源添加锁。如果要对其他共享资源对象进行锁定,则要使用同步监视器
public void xxx(){ //其中ob就是想要锁住的任意的共享资源对象 //代码块是放在同步监视器中的 synchronized(obj){ .... } }
需要注意的是,这样的锁理论上是可行的 ,但是在实际运行中虽然加了锁,但是还是有可能出现不安全的现象