`
8366
  • 浏览: 815677 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

多线程回顾

阅读更多

基本概念:

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

@后台线程的概念: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;
        }
}

分享到:
评论

相关推荐

    C++面向对象多线程编程

    《C++面向对象多线程编程》共分13章,全面讲解构建多线程架构与增量多线程编程技术。第1章介绍了用于构建面向对象程序的不同类型C++组件,以及如何使用这些组件来构建多线程架构。第2、3、4章简要介绍进程、线程、多...

    java多线程设计模式详解(PDF及源码)

    重点回顾 练习问题 Introduction 2 多线程程序的评量标准 多线程程序的评量标准 安全性——不损坏对象 生存性——进行必要的处理 复用性——可再利用类 性能——能快速、大量进行处理 评量标准的总结 重点回顾 练习...

    Python异步编程详解【305263】回顾多线程,多进程,生成器概念.zip

    本文将深入探讨Python中的异步编程概念,包括回顾多线程、多进程以及生成器,并结合提供的课件和代码示例进行详细解释。 首先,多线程是并发执行任务的一种方式。在Python中,`threading`模块提供了创建和管理线程...

    python 多线程串行和并行的实例

    在讨论具体代码之前,我们先回顾一下多线程的基本概念。 ##### 1.1 什么是多线程? 多线程是指在一个进程中同时运行多个线程来执行不同的任务。每个线程都是进程的一个执行单元,它们共享相同的内存空间和其他资源...

    Win32多线程程序设计(pdf加全书签)

    《Win32多线程程序设计》是一本深入探讨C++在Win32平台上实现多线程编程的专业书籍。该书全面覆盖了多线程技术的基础理论与实践应用,为开发者提供了详尽的指导。书中的"加全书签"功能使得读者能够更方便地定位和...

    USB多线程数据管理论文.doc

    由于多线程编程可以显著提高系统并行处理数据的能力,因此在软件层面上,实现了一个高效的多线程管理机制,以确保多个线程之间能够协调一致地工作,而不会互相干扰。此外,本论文还提出了一系列优化措施,例如线程...

    VB可不可以创建多线程

    在开始之前,我们先简要回顾一下多线程的基础概念: 1. **进程**:进程是指程序在一个数据集合上运行的过程,是操作系统进行资源分配和调度运行的一个独立单位。简单来说,进程就是程序的一次执行。 2. **线程**:...

    JAVA多线程设计模式.pdf 下载

    在深入讨论多线程设计模式之前,我们先简要回顾一下Java中多线程的基础概念。Java通过`java.lang.Thread`类提供了创建线程的基本功能。每个`Thread`对象代表一个独立的执行路径,可以通过调用`start()`方法启动线程...

    多线程死锁,活锁,竞争锁问题总结

    在探讨多线程编程中常见的问题之前,我们首先简要回顾一下多线程的基本概念。多线程是一种允许多个线程在同一进程中并发执行的技术。每个线程都拥有独立的执行路径,可以并行地执行不同的任务或同一任务的不同部分。...

    Java多线程与并发库高级应用视频教程22集

    资源名称:Java多线程与并发库高级应用视频教程22集资源目录:【】01传统线程技术回顾【】02传统定时器技术回顾【】03传统线程互斥技术【】04传统线程同步通信技术【】04传统线程同步通信技术_分割纪录【】05线程...

    POSIX多线程程序设计中文版 (1概述)

    ### POSIX多线程程序设计知识点总结 #### 1. 概述 - **线程定义**:线程是在计算机中负责执行一系列机器指令的最小单位,包含必要的机器状态信息,如指令指针、地址和数据寄存器等。 - **线程与进程的区别**:线程...

    qt3.rar_Linux QT_qt3 多线程_qt多线程

    QT3是Qt库的一个早期版本,它在20世纪末和21世纪初被广泛用于开发跨平台的GUI应用程序。这个“qt3.rar”压缩包...同时,它也可能是对旧版Qt技术的一个回顾,对于理解现代Qt(如Qt5或Qt6)的多线程概念也非常有帮助。

    C++面向对象多线程编程(part2)

    全书共分13章,全面讲解构建多线程架构与增量多线程编程技术。第1章介绍了用于构建面向对象程序的不同类型C++组件,以及如何使用这些组件来构建多线程架构。第2、3、4章简要介绍进程、线程、多任务处理、多线程化、...

    C++多线程编程

    在深入了解C++多线程编程之前,我们需要先对进程和线程的基本概念进行简要回顾。 ##### 进程与线程的历史背景 早期计算机系统设计时,由于硬件资源限制,一个程序独占整个系统的资源进行运行是非常普遍的做法。...

    移动编程之线程

    Java的线程回顾 匿名内部类 Android的多线程技术之Handler Android的多线程技术之AsyncTask HTTP概述 HTTPClient

    C# 多线程 应用程序 实例 程序 说明文件

    4. "多线程笔记.rar":这可能是一份详细的笔记文档,整理了关于C#多线程的关键点,包括理论知识、常见问题和解决方案,对于学习和回顾多线程技术非常有帮助。 这些文件共同构成了一个全面的学习资源,可以帮助...

    易语言多线程经典学习源码

    首先,我们来简要回顾一下多线程的概念。多线程是一种允许多个线程执行的计算模型,每个线程可以看作是一个独立的执行路径。在传统的单线程编程模型中,程序按照既定的顺序执行,而多线程则打破了这一模式,允许多个...

    Multi-ThreadTest.rar_win32 多线程

    在IT领域,多线程是程序设计中的一个重要概念,尤其在Windows系统环境下,掌握Win32 API进行多线程...对于初学者来说,这是一个很好的起点,而对于经验丰富的开发者,这则是一个回顾和验证Win32多线程技术的实用案例。

Global site tag (gtag.js) - Google Analytics