`
神绮_H_亚里亚
  • 浏览: 10527 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

线程(上)

阅读更多

1. 什么是线程 

        传统的程序设计语言同一时刻只能执行单任务操作,效率非常低,如果网络程序在接收数据时发生阻塞,只能等到程序接收数据之后才能继续运行。随着 Internet 的飞速发展,这种单任务运行的状况越来越不被接受。如果网络接收数据阻塞,后台服务程序就会一直处于等待状态而不能继续任何操作。这种阻塞情况经常发生,这时的 CPU资源完全处于闲置状态。

         多线程实现后台服务程序可以同时处理多个任务,并不发生阻塞现象。多线程是 Java 语言的一个很重要的特征。多线程程序设计最大的特点就是能够提高程序执行效率和处理速度。Java 程序可同时并行运行多个相对独立的线程。例如创建一个线程来接收数据,另一个线程发送数据,既使发送线程在接收数据时被阻塞,接受数据线程仍然可以运行。 线程(Thread)是控制线程(Thread of Control)的缩写,它是具有一定顺序的指令序列(即所编写的程序代码)、存放方法中定义局部变量的栈和一些共享数据。线程是相互独立的,每个方法的局部变量和其他线程的局部变量是分开的,因此,任何线程都不能访问除自身之外的其他线程的局部变量。如果两个线程同时访问同一个方法,那每个线程将各自得到此方法的一个拷贝。 

       Java 提供的多线程机制使一个程序可同时执行多个任务。线程有时也被称为小进程,它是从一个大进程里分离出来的小的独立的线程。由于实现了多线程技术,Java 显得更健壮。多线程带来的好处是更好的交互性能和实时控制性能。多线程是强大而灵巧的编程工具,但要用好它却不是件容易的事。在多线程编程中,每个线程都通过代码实现线程的行为,并将数据供给代码操作。编码和数据有时是相当独立的,可分别向线程提供。多个线程可以同时处理同一代码和同一数据,不同的线程也可以处理各自不同的编码和数据。 

2 .创建线程方法

       Java程序都是声明一个公共类,并在类内实现一个 main 方法。事实上,这些程序就是一个单线程程序。当它执行完main 方法的程序后,线程正好退出,程序同时结束运行。

 

public class OnlyThread {  
    public static void main(String args[]) {  
        run(); // 调用静态run()方法  
    }  
  
    /** 
     * 实现run()方法 
     */  
    public static void run() {  
	        // 循环计算输出的*数目  
	        for (int count = 1, row = 1; row < 10; row++, count++) {  
	            for (int i = 0; i < count; i++) { // 循环输出指定的count数目的*  
	                System.out.print('*');   
	            }  
	            System.out.println();  
	        }  
	    }  
	}  

 

 

  只是建立了一个单一线程并执行的普通小程序,并没有涉及到多线程的概念。

       Java程序中,有两种方法创建线程:
       
一是对 Thread 类进行派生并覆盖 run方法;

        二是通过实现 runnable接口创建。 

3. Thread 创建线程

     在程序中创建新的线程的方法之一是继承 Thread 类,并通过 Thread子类声明线程对象。继承Thread 类并覆盖 Thread类的 run 方法完成线程类的声明,通过new创建派生线程类的线程对象。run 中的代码实现了线程的行为。 

 

      java.lang.Thread 类是一个通用的线程类,由于默认情况下 run 方法是空的,直接通过 Thread类实例化的线程对象不能完成任何事,所以可以通过派生 Thread 类,并用具体程序代码覆盖Thread 类中的 run 方法,实现具有各种不同功能的线程类。

 

      1) Thread 创建线程步骤: 

 

     1)创建一个新的线程类,继承 Thread 类并覆盖 Thread 类的 run()方法。 

 

	class ThreadType extends Thread{   
	     public void run(){   
	         ……   
	     }   
	}   

 

 

2)创建一个线程类的对象,创建方法与一般对象的创建相同,使用关键字new完成。

 

	ThreadType  tt = new ThreadType();  

 (3)启动新线程对象,调用 start()方法。

 

 

	tt.start();

 (4)线程自己调用 run()方法。

 

 

void run(); 

 

 

 

  2) Thread创建一个线程

 

     

class ThreadDemo1 extends Thread {  
    ThreadDemo1() {  
    }  
  
    // 声明ThreadDemo1带参数的构造方法  
    ThreadDemo1(String szName) {  
        super(szName);  
    }  
  
	    // 重载run函数  
	    public void run() {  
	        for (int count = 1, row = 1; row < 10; row++, count++) {  
	            for (int i = 0; i < count; i++) {// 循环输出指定的count数目的*  
	                System.out.print('*');  
	            }  
	            System.out.println();  
	        }  
	    }  
	  
	    public static void main(String argv[]) {  
	        ThreadDemo1 td = new ThreadDemo1(); // 创建,并初始化ThreadDemo1类型对象td  
	        td.start(); // 调用start()方法执行一个新的线程  
	    }  
	}  

 

 

 

  OnlyThread.java程序与程序ThreadDemo1.java表面上看运行结果相同,但是仔细对照会发现,程序OnlyThread.java中对 run方法的调用在程序ThreadDemo1.java中变成了对 start 方法的调用,并且程序ThreadDemo1.java确派生 Thread类,创建新的线程类。 

 

 3) Thread创建多个线程

//产生三个新的线程 
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

public class ThreadDemo2 extends Thread {  
    // 声明无参数,空构造方法  
    ThreadDemo2() {  
    }  
  
    // 声明带有字符串参数的构造方法  
    ThreadDemo2(String szName) {  
        super(szName); // 调用父类的构造方法  
    }  
	  
	    // 重载run函数  
	    public void run() {  
	        for (int count = 1, row = 1; row < 10; row++, count++) {  
	            for (int i = 0; i < count; i++) {// 循环输出指定的count数目的*  
	                System.out.print('*');  
	            }  
	            System.out.println();  
	        }  
	    }  
	  
	    public static void main(String argv[]) {  
	        ThreadDemo2 td1 = new ThreadDemo2(); // 创建,并初始化ThreadDemo2类型对象td1  
	        ThreadDemo2 td2 = new ThreadDemo2(); // 创建,并初始化ThreadDemo2类型对象td2  
	        ThreadDemo2 td3 = new ThreadDemo2(); // 创建,并初始化ThreadDemo2类型对象td3  
	        td1.start(); // 启动线程td1  
	        td2.start(); // 启动线程td2  
	        td3.start(); // 启动线程td3  
	    }  
	}  

 创建了 3 个线程 td1td2td3,它们分别执行自己的 run方法。在实际中运行的结果并不是想要的直角三角形,而是一些乱七八糟的 “*” 行,长短并没有一定的规律,这是因为线程并没有按照程序中调用的顺序来执行,而是产生了多个线程赛跑现象。 运行结果:

 

 注意:Java线程并不能按调用顺序执行,而是并行执行的单独代码。如果要想得到完整的直角三角形,需要在执行一个线程之前,判断程序前面的线程是否终止,如果已经终止,再来调用该线程。

 

 

4. Runnable 接口创建线程 

 

        通过实现 Runnable 接口的方法是创建线程类的第二种方法。利用实现 Runnable 接口来创建线程的方法可以解决 Java 语言不支持的多重继承问题                Runnable 接口提供了 run()方法的原型,因此创建新的线程类时,只要实现此接口,即只要特定的程序代码实现Runnable接口中的 run()方法,就可完成新线程类的运行。

 

      扩展Thread类创建线程的方式,适合编写简单的应用程序代码,而实现Runnable接口创建线程,能够避免Java单继承的局限,适合同一代码的多线程处理同一资源的情况,代码具有良好的一致性,是更符合面向对象思想的设计方式。

 

     1) Runnable 创建线程步骤 

   1)创建一个实现 Runnable 接口的类,并且在这个类中重写 run 方法。

 

 

	class ThreadType implements Runnable{   
	     public void run(){   
	         ……   
	     }   
	}   

 2)使用关键字 new新建一个 ThreadType 的实例。

Runnable rb = new ThreadType ();   

 3)通过 Runnable 的实例创建一个线程对象,在创建线程对象时,调用的构造函数是new Thread(ThreadType),它用 ThreadType 中实现的 run()方法作为新线程对象的 run()方法。 

 

	Thread td = new Thread(rb);  

 4)通过调用 ThreadType 对象的 start()方法启动线程运行。 

	td.start();   

  2) Runnable 创建线程

 

 

class ThreadDemo3 implements Runnable {  
       // 重载run函数  
       public void run() {  
           for (int count = 1, row = 1; row < 10; row++, count++){ // 循环计算输出的*数目  
               for (int i = 0; i < count; i++){ // 循环输出指定的count数目的*  
                   System.out.print('*');   
               }  
               System.out.println();   
           }  
     }  
   
     public static void main(String argv[]) {  
         Runnable rb = new ThreadDemo3(); // 创建,并初始化ThreadDemo3对象rb  
         Thread td = new Thread(rb); // 通过Thread创建线程  
         td.start(); // 启动线程td  
     }  
 }  

 

 

分享到:
评论

相关推荐

    易语言源码易语言线程上下文注入源码.rar

    易语言源码易语言线程上下文注入源码.rar 易语言源码易语言线程上下文注入源码.rar 易语言源码易语言线程上下文注入源码.rar 易语言源码易语言线程上下文注入源码.rar 易语言源码易语言线程上下文注入源码.rar ...

    c#Winform异步线程刷新UI

    在这个示例中,`LongRunningOperation`方法在后台线程上执行,而`btnStart_Click`方法则继续执行,不会阻塞UI。`Invoke`方法确保在UI线程上安全地更新进度条。 通过正确使用异步编程,我们可以创建出既高效又用户...

    C# 跨线程访问UI线程控件

    在C#中,由于使用线程和调用UI的线程属于两个不同的线程,如果在线程中直接设置UI元素的属性,此时就会出现跨线程错误。    下面介绍两种解决方案  第一种:使用控件自带的Invoke或者BeginInvoke方法。 Task....

    C#_细说多线程(上下)

    PLINQ能够自动地将查询操作分解到多个线程上执行,从而提高查询效率。 #### 八、计时器与锁 - **计时器**:`System.Threading.Timer` 类可用于实现定时任务。与`System.Timers.Timer`不同的是,前者更加高效且适合...

    16丨多线程调优(下):如何优化多线程上下文切换?.html

    16丨多线程调优(下):如何优化多线程上下文切换?.html

    C# 多线程实例多线程实例多线程实例

    多线程允许一个应用程序同时执行多个任务,每个任务都在一个独立的线程上运行。C#中,我们可以通过System.Threading命名空间下的类来创建和管理线程。主线程是应用程序启动时默认创建的,而额外的线程可以由开发者...

    PB多线程实现

    一种常见的方式是创建一个新的窗口类,该窗口类在不同的线程上运行。通过调用如CreateThread或BeginThread等API函数,可以在新的线程上下文中启动这个窗口类。同时,需要处理线程同步问题,例如使用Mutex、Semaphore...

    .NET多线程实例

    在多线程环境中,事件处理通常在引发事件的线程上运行,因此,如果一个线程修改了UI控件的状态,而另一个线程尝试处理相关事件,可能会导致线程不安全。使用适当的同步机制可以解决这个问题。 "资源管理器"可能涉及...

    Java多线程机制(讲述java里面与多线程有关的函数)

    为了确保UI的响应性,所有对UI的操作应在这个线程上进行。 9.6 线程同步: 线程同步是解决多线程环境下数据安全问题的关键。Java提供了synchronized关键字来实现方法或代码块的同步,防止多个线程同时访问同一块...

    C# 线程更新UI界面

    - `Control.Invoke`:用于在UI线程上执行指定的委托。如果当前线程是UI线程,方法会立即执行;否则,它会在UI线程的的消息队列中排队,等待执行。 - `Control.BeginInvoke`:异步版本的Invoke,它会将方法调用放入...

    C#多线程刷新界面

    1. **BackgroundWorker组件**:这是.NET Framework提供的一种简单易用的多线程解决方案,适合在UI线程中启动,并在工作线程上执行任务。BackgroundWorker提供了ProgressChanged和RunWorkerCompleted事件,可以在UI...

    Qt线程之间通信、线程和进程之间通信实例

    2. 信号和槽:使用`connect()`函数建立信号和槽的连接,可以指定线程上下文,确保信号和槽在正确的线程中执行。 3. `QMutex`和`QWaitCondition`:用于线程同步,防止数据竞争。`QMutex`用于保护共享资源,`...

    VB单元线程模型实现多线程

    在这里,`MyThreadFunction`是你定义的函数,它将在新线程上执行。 2. **线程同步与互斥**:在多线程环境中,线程同步是必要的,以防止多个线程同时访问共享资源,可能导致数据不一致。VB提供了`Mutex`类来实现...

    利用VB6实现多线程

    这样,每一个控件或对象都会在自己的线程上运行,实现真正的多线程。 3. 编写线程代码 在ActiveX EXE工程中编写线程要执行的代码。通常,我们会创建一个类模块(Class Module),然后在这个类模块中定义线程函数,...

    多线程与单线程的对比(采用CreateThread)

    相比之下,多线程允许程序同时执行多个独立的任务,每个任务在不同的线程上运行。这提高了程序的响应性和并发性,尤其是在现代多核处理器环境中。然而,多线程也带来了额外的复杂性,如线程同步、竞态条件和死锁等...

    大漠的c#多线程模板

    最后,`BackgroundWorker`组件提供了一种在后台线程上执行耗时操作的方式,同时允许在UI线程上更新进度和处理结果,这对于GUI应用特别有用。 综上所述,"大漠的c#多线程模板"应该包含了如何创建线程、使用线程池、...

    delphi多线程访问数据库

    首先,多线程的基本概念是并发执行多个任务,每个任务在一个独立的线程上运行。在Delphi中,我们可以使用TThread类或VCL库中的其他多线程组件来创建和管理线程。例如,`Unit1`和`Unit2`可能是两个不同的线程类,分别...

    WPF 使用线程更新UI

    1. **后台线程与主线程**:主线程是负责处理UI事件的线程,任何对UI的操作必须在这个线程上执行。后台线程则用于处理非UI相关的工作,如大数据计算、网络请求等,以避免阻塞主线程。 2. **Dispatcher对象**:每个...

    C#线程间操作无效Study

    这两个方法会确保在正确的线程上下文中执行操作。例如: ```csharp if (this.InvokeRequired) { this.Invoke(new Action(() =&gt; { // 在这里修改UI元素 textBox.Text = "新文本"; })); } else { // 直接...

    采用AfxBeginThread创建工作线程

    它们不会影响用户界面的响应性,因为它们不在UI线程上运行。通过`AfxBeginThread`创建的工作线程,可以避免长时间计算导致的UI冻结。 3. **多线程编程** 多线程编程允许应用程序同时执行多个任务,提高资源利用率...

Global site tag (gtag.js) - Google Analytics