线程的简介
多线程是实现并发机制的一种有效的手段。进程和线程一样,都是实现并发的一个基本单位。只不过线程是比进程更小的执行单位,而且线程组成进程。
多线程机制可以同时运行多个程序模块,是程序运行的效率变得更高。
线程的状态
(1)创建状态:创建一个线程对象后,新的线程对象便处于新建状态,例如”Thread thread=new Thread();”
(2)就绪状态:调用start()方法,线程进入线程队列排队,等待CPU服务
(3)运行状态:就绪的线程被调用并且获取处理器资源时候,线程就进入了运行状态。此时,自动调用该线程对象的run()方法
(4)堵塞状态:调用sleep(),suspend()、wait()等方法。堵塞时,线程不能进入排队队列,只有将堵塞的原因被消除后,相爱难成才可以转入就绪状态
(5)死亡状态:线程调用stop()方法时候或者run()方法执行结束后
线程的实现
继承Thread实现
package com.thread.blog;
public class Demo1 extends Thread {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo1 d1=new Demo1();
Demo1 d2=new Demo1();
d1.setName("线程A");
d2.setName("线程B");
d1.start();
d2.start();
}
public void run(){
for(int i=1;i<11;i++){
System.out.println("线程为"+Thread.currentThread().getName()+"执行了"+i);
}
}
}
继承Runnable接口
package com.thread.blog;
public class Demo2 implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo2 d1=new Demo2();
Demo2 d2=new Demo2();
Thread t1=new Thread(d1,"able1");
Thread t2=new Thread(d2,"able2");
t1.start();
t2.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=1;i<11;i++){
System.out.println("线程为"+Thread.currentThread().getName()+"执行了"+i);
}
}
}
线程的基本方法
Sleep与yield区别
package com.thread.blog;
/**
* 总结:
* (1)这里是展示Thread.sleep()方法,主要是休眠当前线程
* (2)之后执行的线程,不分优先级的等级
* (3)不会释放锁资源
* @author DearMind-Hack
*
*/
public class Demo3 implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo3 Demo3=new Demo3();
Thread th=new Thread(Demo3,"线程A");
th.start();
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("子线程"+Thread.currentThread().getName());
}
}
package com.thread.blog;
public class Demo4 implements Runnable{
/**
* (1)这个例子展示了,即使设置thread.setPriority(),每次执行的顺序也不一定
* (2)yield()核心意思就是重新洗牌,当前线程变为就绪状态,然后新一轮的抢CPU开始了,
* 区别:sleep()重新洗牌,不包括当前线程,而yield()包括而已
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo4 d1=new Demo4();
Demo4 d2=new Demo4();
Thread th1=new Thread(d1,"线程A");
Thread th2=new Thread(d2,"线程B");
th1.setPriority(Thread.MAX_PRIORITY);
th2.setPriority(Thread.MIN_PRIORITY);
th1.start();
th2.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
Thread.yield();
System.out.println("线程"+Thread.currentThread().getName()+" "+i);
}
}
}
stop方法
可以用来终止一个线程,但是不安全,建议不要使用此方法来停止线程。
注: stop方法是立即停止当前线程, 这样停止的后果是导致stop后的语句无法执行, 有可能资源未释放. 列或者在同步块中调用此方法会导致同步数据会不完整. 所以需禁用此方法. 由于stop方法的特释性, 将不给出示范代码.
join()
package com.thread.blog;
public class Demo5 implements Runnable{
/**
* join()方法
* (1)从这个例子可以看到,0---9,是主线程和线程A并发的执行,当线程A调用
* join()方法后,仅仅执行线程A。只有当线程A执行完毕之后,才会执行主线程。
*/
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo5 d1=new Demo5();
Thread th1=new Thread(d1,"线程A");
th1.start();
for(int i=0;i<50;i++){
if(i>10){
try {
th1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("主函数执行"+" "+i);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
System.out.println(Thread.currentThread().getName()+"运行--》"+i);
}
}
}
先执行当前线程,等该线程执行完毕之后,才能执行别的线程。
注: join函数为线程安全函数, 即同步函数. 也就是当ThreadJoin类的run用synchronized锁住时, t.join方法将得不到锁资源而等待更长的时间.
interrupt() 与isInterrupted()区别
(1)public boolean isInterrupted();
判断线程是否在活动,若果是返回true;否则返回false;
(2)interrupt()
package com.thread.blog;
/**
* @author DearMind-Hack
* (1)我对此方法的理解就是,叫醒一个正在阻塞的线程,返回就绪状态
*
* */
public class Demo6 implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo6 d1=new Demo6();
Thread th1 =new Thread(d1,"线程A");
th1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
th1.interrupt();
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("1、 进入run方法");
try {
Thread.sleep(10000);
System.out.println("2、 已经完成休眠");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("3、休眠被终止");
return;
}
System.out.println("4、 程序正常结束");
}
}
线程的同步
一个多线程通过Runnable接口实现,意味着类的属性将被多个线程共享,这样一类就会造成资源的同步问题,例如:买票卖出负票。因此需要同步代码。
线程的同步分为:同步代码块和同步方法。
同步代码块
package com.thread.blog;
/**
* (1)解决资源同步的问题,使用同步代码块或者同步方法的完成
* (2)
* */
public class Demo8 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread my=new MyThread();
Thread thread1=new Thread(my,"线程A");
Thread thread2=new Thread(my,"线程B");
Thread thread3=new Thread(my,"线程C");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyThread implements Runnable{
int ticket=10;
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
synchronized (this) {
if(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程名字为:"+Thread.currentThread().getName()+"出售了"+ticket--);
}
}
}
}
}
同步方法
package com.thread.blog;
/**
*
*
* */
public class Demo9 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TwoThread two=new TwoThread();
Thread thread1=new Thread(two,"线程A");
Thread thread2=new Thread(two,"线程B");
Thread thread3=new Thread(two,"线程C");
thread1.start();
thread2.start();
thread3.start();
}
}
class TwoThread implements Runnable{
int ticket=10;
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
if(ticket>0){
this.sale();
}
}
}
public synchronized void sale(){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程名字为:"+Thread.currentThread().getName()+"出售了"+ticket--);
}
}
线程的死锁
两个线程都在等待对方先完成,造成了程序的停滞。