• 多线程


    多线程  概述

    1.进程:是一个正在执行中的程序。

    每个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元(线程)。

    2.线程:就是进程中的一个独立的控制单元。

    线程控制着进程的执行,一个进程中,至少有一个或一个以上的线程。

    创建线程的第一种方式:继承Thread类。

    步骤:

    1.定义类继承Thread。

    2.复写Thread类中的run方法(目的:将自定义代码存储在run方法。让线程运行)

    3.调用线程的Start方法,该方法两个作用:启动线程,调用run方法(直接调用run方法也是可以的,但是那样就不是多线程了)

     1 class ThreadTest extends Thread{ 
     2 
     3 
     4 
     5         public void run(){ 
     6 
     7 
     8 
     9         线程运行代码; 
    10 
    11         } 
    12 } 
    13 
    14 class Test{ 
    15 
    16         public static void main(String[] args){ 
    17 
    18 
    19         ThreadTest threadTest = new ThreadTest(); 
    20 
    21         thread.start(); 
    22 
    23         } 
    24 
    25 } 
    26 
    27 
    28 
    29                     

    也可以使用匿名内部类的方式:

     1 class Test{ 
     2 
     3         public static void main(String[] args){ 
     4 
     5                 new Thread(){ 
     6 
     7                     public void run(){ 
     8 
     9                     线程运行代码; 
    10 
    11                     } 
    12 
    13                 }.start(); 
    14 
    15         } 
    16 
    17 } 

    创建线程的第二种方式:实现Runnable接口

    实现步骤:

    1.定义类实现Runnable接口
    2.覆盖Runnable接口中的run方法,将线程要运行的代码存放在该run方法中。

    3.通过Thread建立线程对象

    4.Runnable接口的子类对象作为实际参数传递给Thread的构造函数。

    5.调用Thread类的start方法开启线程并调用Runnable接口子类的的run方法。

     1 class RunnableTest implements Runnable{ 
     2 
     3         public void run(){ 
     4 
     5 
     6         线程要运行代码; 
     7 
     8         } 
     9 
    10 }
    11 
    12 class TestDemo{ 
    13 
    14         public static void main(String[] args){ 
    15 
    16             RunnableTest runnableTest = new RunnableTest();
    17             Thread thread = new Thread(runnableTest);
    18             thread.start();
    19         /*
    20         简化到一步  new Thread(new Runnable()).start();
    21 
    22         */ 
    23 
    24         } 
    25 
    26 
    27 } 

    使用匿名内部类:

     1 class TestDemo{ 
     2 
     3         public static void main(String[] args){ 
     4 
     5                 new Thread(new Runnable(){ 
     6     
     7                         public void run(){ 
     8 
     9                             线程要运行代码; 
    10 
    11                         } 
    12                 }).start(); 
    13 
    14         } 
    15 
    16 } 

    为什么要将Runnable接口的子类对象传递给Thread的构造函数。

    因为,自定义的run方法所属的对象是Runnable接口的子接口对象。 所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

    实现方式和继承方式有什么区别:

    (1)、实现方式好处:避免了单继承的局限性。

    (2)、在定义线程时:建议使用实现方式

     

    (3)、两种方式区别:

    1.继承Thread:线程代码存放在 Thread 子类 run 方法中(单继承)

    2.实现Runnable:线程代码存放在接口的子类的 run 方法中(建议使用这种方式,可以实现多继承接口)

     

    多线程好处:

    原本我们如果是单线程的情况下,我们定义在死循环就一直运行死循环的代码,不会运行其他的代码。 多线程的好处就体现出来了,他可以让我们的代码实现同步运行。

    发现运行结果每一次都不同

    因为多个线程都获取CPU的执行权。CPU执行到谁,谁就运行。

    明确一点,在某一个时刻,只能有一个序在运行。(多核除外)。

    CPU在做着快速的切换,以达到看上去是同时运行的效果。

    线程(Thread)类中已经封装好的方法:

    static Thread currentThread():获取当前线程对象。

    getName(): 获取线程名称。 设置线程名称:setName或者构造函数。(线程都有自己默认的名字,Thread-编号 该编号从0开始。

    注意:主线程不会设置名称,它的线程名是默认的(main);

     

    线程间的通讯通信

     

    线程间通信-等待唤醒机制

    wait(),notify(),notifyAll(),都使用在同步中,因为要对持有监视器(锁)的线程操作。

    这些方法在操作同步中,线程同步,都必须要表示它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁notify唤醒,不可以对不同锁中的线程进行等待唤醒。 也就是说,等待和唤醒必须是同一个锁。所以要使用在同步中,因为只有同步才具有锁。

    wait()   sleep()的区别

     

    wait()   :释放资源,释放锁 。

    sleep()   :释放资源,不释放锁。

    其实就是多个线程在操作同一个但是操作的动作不同(一个是wait 一个是notify)。

    同步:

    对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。

    好处:解决了多线程的安全问题

    弊端:多个线程需要判断锁,较为消耗资源。

    package com.lovo;
    /**
     * 同步代码块
     * @author Mine
     *
     */
    public  class Sync implements Runnable{
            private int value;
            
            public void run(){
                for(int count=0;count<3;count++){
                    synchronized(this){//当使用对象锁时,其他线程是无法使用这个块的代码 ,所以value的值是连续的
                        value++;
                        try {
                            Thread.sleep(1000);//线程休眠
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName()+":value="+value);//打印value的值
                    
                }
            }
    }
    
    
    package com.lovo;
    
    public class SyncTest {
            public static void main(String[] args){
                Sync s=new Sync();
                new Thread(s).start();
                new Thread(s).start();
            }
    }
    package com.lovo;
    /**
     * 同步方法
     * @author Mine
     *
     */
    public class Syncc implements Runnable {
            private int value;
            
            public void run(){
                printValue();
            }
            
           public synchronized void printValue(){
                for(int count=0;count<3;count++){
                    value++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        
                    }
                    System.out.println(Thread.currentThread().getName()+"value="+value);
                }
                
            }
    }
    
    
    package com.lovo;
    
    public class SynccTest {
            public static void main(String[] args){
                Syncc s=new Syncc();
                new Thread(s).start();
                new Thread(s).start();
            }
    }
  • 相关阅读:
    Linux Shell常用shell命令
    shell ls
    [转]推荐一些不错的计算机书籍
    What does it mean when you assign [super init] to self?
    保存,读取与多任务处理
    程序媛去过的地方
    读取pcap文件,过滤非tcp包,获取IP及tcp端口信息
    IM实现联系人及联系人分组的数据库设计
    【原创】校园网用户,1个账号2个笔记本上网,Ad hoc无线连网应用
    【openfire插件开发】群组聊天中的中介者模式
  • 原文地址:https://www.cnblogs.com/Melony/p/4471542.html
Copyright © 2020-2023  润新知