一、线程的创建
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实际上就是在操作系统中启动了一个进程。
继承Thread类或者实现runnable的接口。两者的区别:
实现Runnable的好处:
1,、继承Thread类不适合资源的共享,而实现Runnable适合共享资源。
2、避免单继承的局限性。
3.代码可以被多个线程共享,代码和数据实现独立。
二、线程的状态
1.初始状态:线程对象被创建。
2.就绪状态:调用了start()方法,线程变得可以运行。
3.运行状态:就绪状态的线程获取了CPU执行权,开始执行代码。
4.阻塞状态:线程暂时停止执行。阻塞分成三种情况:
(1)等待阻塞:运行的线程执行了wait()方法。jvm将其反放入等待池中。
(2)同步阻塞:多个线程获取同步锁的时候,同步锁被其他的线程暂用,此时线程放入锁池中,等待。
(3)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5.死亡状态:该线程执行完毕或者因为异常退出了run()方法。该线程的生命周期结束。
常用的函数:
1.join()指等待t线程终止。
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
3.sleep(long millis) 在指定的时间内让这个线程处于休眠状态。
3.yield():暂停当前正在执行的线程对象,并执行其他线程。
4.setPriority(): 更改线程的优先级。getPriority()获得当前线程的优先级。
Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
static int MAX_PRIORITY 线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY 线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY 分配给线程的默认优先级,取值为5。
5.interrupt():中断某个线程,这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭
6.wait和sleep区别
共同点:他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回.
不同点:1.Thread类的方法:sleep(),yield()等 Object的方法:wait()和notify()等
2.Synchronized关键字可以和对象的锁交互,来实现线程的同步。sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
.
常见的线程名词
主线程:JVM调用程序main()所产生的线程。
当前线程:一般指通过Thread.currentThread()来获取的进程。
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。用户线程和守护线程的区别在于,是否等待主线程依赖于主线程结束而结束。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。
同步函数与同步代码快的区别
同步代码块:
synchronized(对象){//这个对象可以任意指定
需要被同步的代码}
同步函数是把synchronized加在方法上,如果方法是非static对象锁是this.如果是static则使用的是.class字节码文件。
线程安全问题
线程安全:
就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全:
就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。