多线程回顾

基本概念:

@程序是计算机指令的集合,它以文件的形式存储在磁盘上。
@进程:是一个程序在其自身的地址空间中的一次执行活动。
进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。
@线程:是进程中的一个单一的连续控制流程。一个进程可以拥有多个线程。
线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。

@后台线程的概念:main 方法是一个非后台线程,当一个程序没有非后台线程在运行的时候,jvm就要退出了.可以使用线程对象的setDaemon()来设置后线程.

yield() 方法可暂是放弃线程的执行权力.

线程的优先级 0(Thread.MIN_PRIORITY).5(Thread.NORM_PRIORITY),10(Thread.MAX_PRIORITY)


Java在语言级提供了对多线程程序设计的支持。
实现多线程程序的两种方式:
    (1)从Thread类继承;
   
    package cn.com.xinli.test.miti;


        public class TestMitiThread
        {
            public static void main(String[] rags) throws Exception
            {
             
                    MitiSay ms=  new MitiSay("A");
                    ms.start();
                    System.out.println(Thread.currentThread().getName());
              
            }
        }
        
        class MitiSay extends Thread //implements  Runnable
        {
               
                public MitiSay(String name)
                {
                        super(name);
                }
                public void  run()
            {
                       
                                System.out.println("线程"+Thread.currentThread().getName());
                               
            }
               
        }

 

    (2)实现Runnable接口。
   
   
        public class TestMitiThread
        {
            public static void main(String[] rags) throws Exception
            {
             
                    MitiSay ms=  new MitiSay();
                    new Thread(ms).start();
                    System.out.println(Thread.currentThread().getName());
              
            }
        }
        
        class MitiSay  implements  Runnable
        {
               
               
                public void  run()
            {
                       
                                System.out.println("线程"+Thread.currentThread().getName());
                               
            }
               
        }

   让多个线程访问一个共享的变量:
方式1.使用Runnable 接口实现,因为继承Thread,多个线程就会有多个变量的拷贝
方式2.使用内部类,可以随意的访问外部类的变量和方法,记得在外部类中写一个得到内部类的方法就ok了
public class TestMitiThread
        {
            public static void main(String[] rags) throws Exception
            {
             
               
                MitiSay ms=new MitiSay();
                ms.getInnerThread().start();
                ms.getInnerThread().start();
                ms.getInnerThread().start();
                ms.getInnerThread().start();
              
            
              
            }
        }
        
        class MitiSay // implements  Runnable
        {
                int index=100;
               
                 class InnerThread extends Thread
                {
                                 public void  run()
                            {
                                       
                                       
                                        while(true)
                                        {
                                                if(index<0)
                                                        break;
                                                System.out.println("线程"+Thread.currentThread().getName()+":"+index--);
                                               
                                                //        Thread.yield();
                                        }
                            }
                }
                public InnerThread getInnerThread()
                {
                        return new InnerThread();
                }
               
        }

以上两中方法都可以打印出联系减少的index变量的值,并且是由不同的线程打印的,时间了多个线程访问一个共享的变量


多线程模拟火车站售票系统:

public class TicketsSystem
{
        public static void main(String[] args)
        {
                SellThread st=new SellThread();
               
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
               
        }
       
}
 class SellThread implements  Runnable
{
        int tickets=100;
        public void run()
        {
                while(true)
                {
                        if(tickets>0)
                        {
                                /*
                                try
                                {
                                        Thread.sleep(1);
                                }
                                catch (InterruptedException e)
                                {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                                */
                                System.out.println(Thread.currentThread().getName()+":sell "+tickets);
                                tickets--;
                               
                        }
                }
        }
       
}

程序打印出从100到1,4个线程卖出的票,但是这个程序有一个潜在的问题,就是在长时间的运行下,有可能打印出0,-1,-2这样的票号,为了重现这种情况,我们把注视的代码打开就运行就可以看到了,也就是说一个线程判断玩剩余的票数之后休眠了,而其他的线程此时却修改了 tickets 变量,然后tickets -- 则会出现0,-1,-2 的票号.原因:是由于多个线程共同访问和修改了 共享的变量 tickets

同步的两种方式:同步块和同步方法
每一个对象都有一个监视器,或者叫做锁。
同步方法利用的是this所代表的对象的锁。
每个class也有一个锁,是这个class所对应的Class对象的锁。

    1.使用同步块技术 保护 关键代码


public class TicketsSystem
{
        public static void main(String[] args)
        {
                SellThread st=new SellThread();
               
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
               
        }
       
}
 class SellThread implements  Runnable
{
        int tickets=100;
        Object o=new Object();
        public  void  run()
        {
                while(true)
                {
                        synchronized(o)
                        {
                                if(tickets>0)
                                {
                               
                                        try
                                        {
                                                Thread.sleep(1);
                                        }
                                        catch (InterruptedException e)
                                        {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                       
                                        System.out.println(Thread.currentThread().getName()+":sell "+tickets);
                                        tickets--;
                                       
                                }
                        }
                }
        }
       
}

2.使用同步方法

public class TicketsSystem
{
        public static void main(String[] args)
        {
                SellThread st=new SellThread();
               
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
                new Thread(st).start();
               
        }
       
}
 class SellThread implements  Runnable
{
        int tickets=100;
        Object o=new Object();
        public  void  run()
        {
                while(true)
                {
                        sell();
                }
        }
        public synchronized void sell()
        {
                if(tickets>0)
                {
               
                        try
                        {
                                Thread.sleep(1);
                        }
                        catch (InterruptedException e)
                        {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                       
                        System.out.println(Thread.currentThread().getName()+":sell "+tickets);
                        tickets--;
                       
                }
        }
}


    


@每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的对待队列是空的。
@我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法,只能在同步方法和同步块钟使用
@当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。
@当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。
@wait和notify主要用于producer-consumer这种关系中

生产者-消费者:利用wait()和notity(),必须使用同一个监视器(this),必须在同步方法和同步块中使用

public class ProductAndConsumer
{
        public static void main(String[] args)
        {
                Queue q=new Queue();
                Product p=new Product(q);
                Consumer c=new Consumer(q);
                p.start();
                c.start();
        }
}

class Queue
{
        int value;
        boolean bFull=false;
        public synchronized void put(int i)
        {
                if(!bFull)
                {
                        value=i;
                        bFull=true;
                        notify();
                }
                try
                {
                        wait();
                }
                catch(Exception e)
                {
                        e.printStackTrace();
                }
                       
        }
        public synchronized int get()
        {
                if(!bFull)
                {
                        try
                        {
                                wait();
                        }
                        catch(Exception e)
                        {
                                e.printStackTrace();
                        }
                }
                bFull=false;
                notify();
                return value;
        }
}

class Consumer extends Thread
{
        Queue q;
        Consumer(Queue q)
        {
                this.q=q;
        }
        public void run()
        {
                while(true)
                {
                        System.out.println("Consumer get "+q.get());
                }
        }
       
       
}
class Product extends Thread
{
        Queue q;
        public Product(Queue q)
        {
                this.q=q;
        }
        public void run()
        {
                for(int i=0;i<10;i++)
                {
                        q.put(i);
                        System.out.println("Product"+"put "+i);
                       
                       
                }
               
        }
}

 

 

 线程的状态变换

 

 


@线程的终止:
设置一个flag变量。
结合interrupt()方法。

方式一:设置一个flag变量。

 

class StopThread
{
        public static void main(String[] args)
        {
                Thread1 t1=new Thread1();
                t1.start();
                int index=0;
                while(true)
                {
                        if(index++==500)
                        {
                                t1.stopThread();
                       
                                break;
                        }
                        System.out.println(Thread.currentThread().getName());
                }
                System.out.println("main() exit");
        }
}

class Thread1 extends Thread
{
        private boolean bStop=false;
        public void run()
        {
                while(!bStop)
                {
                       
                        System.out.println(getName());
                }
        }
        public void stopThread()
        {
                bStop=true;
        }
}

方式一:设置一个flag变量 结合interrupt()方法。

    方式1,如果有业务需要在run()方法中调用了wait()方法,那我们上边的线程就不能终止了,因为它一直处于等待状态,则需要我们使用结合interrupt()方法来终止线程了

class StopThread
{
        public static void main(String[] args)
        {
                Thread1 t1=new Thread1();
                t1.start();
                int index=0;
                while(true)
                {
                        if(index++==500)
                        {
                                t1.stopThread();
                                /*调用这个方法会抛异常*/
                                t1.interrupt();
                                break;
                        }
                        System.out.println(Thread.currentThread().getName());
                }
                System.out.println("main() exit");
        }
}

class Thread1 extends Thread
{
        private boolean bStop=false;
        public synchronized void run()
        {
                while(!bStop)
                {
                        try {
                                wait();
                        } catch (InterruptedException e)
                        {
                                System.out.println("由于调用了interrupt所以抛出异常");
                                if(bStop)
                                        return;
                        }
                        System.out.println(getName());
                }
        }
        public void stopThread()
        {
                bStop=true;
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值