精华内容
下载资源
问答
  • 线程的概述和多线程的意义 JVM运行原理以及JVM启动的线程探讨 实现多线程 线程调度 线程控制 二、进程概述及多进程的意义 A:线程和进程 要想说线程,首先必须得聊聊进程,因为线程是依赖于进程存在的。 B:进程...

    一、多线程

    	进程的概述和多进程的意义
    	线程的概述和多线程的意义
    	JVM运行原理以及JVM启动的线程探讨
    	实现多线程
    	线程调度
    	线程控制
    

    二、进程概述及多进程的意义

    A:线程和进程
    要想说线程,首先必须得聊聊进程,因为线程是依赖于进程存在的。
    B:进程概述
    什么是进程呢?通过任务管理器我们就可以看到进程的存在。
    概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。
    每一个进程都有它自己的内存空间和系统资源。
    C:多进程的意义
    单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音乐进程),
    所以我们常见的操作系统都是多进程操作系统。比如:Windows,Mac和Linux等,能在同一个时间段内执行多个任务。
    对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。
    因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,
    所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。多进程的作用不是提高执行速度,而是提高CPU的使用率。

    线程概述及多线程的意义及并行和并发的区别
    并发(concurrency)和并行(parallellism)是:

    1. 解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
    2. 解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
    3. 解释三:并行是在一台处理器上“同时”处理多个任务,并发是在多台处理器上同时处理多个任务。如 hadoop 分布式集群。

    所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

    三、多线程程序实现的方式1

    public class MyThread extends Thread{
    
        @Override
        public void run() {
            //这个run方法就是需要线程来执行的代码,一般耗时的操作,我们就会写在run方法里面,让线程去执行
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
    -------------------------------------------------------------
    public class MyTest3 {
        public static void main(String[] args) {
       MyThread th = new MyThread();
            //开启线程,不是调用run方法,调用run()方法,就是你使用一个对象,调用一个方法,让这个方法执行而已,线程并没有开启
            //th.run();
            //正确开启线程的方式是,调用start() 开启线程,由线程去调用run()去执行run方法里面的代码
            th.start();
            //th.start(); 同一个线程不要多次开启,会抛异常
            MyThread th2 = new MyThread();
            th2.start();
        }
    }
    

    获取和设置线程对象名称

    如何获取main方法所在的线程名称呢?
    public static Thread currentThread()//获取当前执行的线程
    /**
    * 我们现在是想获取主线程的名称,那么我们可不可以先获取到主线程,
    如果我们能获取到主线程,那么我们就可以调用getName方法获取对应的名称.
    * 如何获取主线程呢? public static Thread currentThread()返回对当前正在执行的线程对象的引用。
    * -----------------------------------------------------------------
    :Thread类的基本获取和设置方法
    public final String getName()//获取线程名称
    public final void setName(String name)//设置线程名称
    其实通过构造方法也可以给线程起名字

    线程调度及获取和设置线程优先级

    线程的执行
    假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,
    线程只有得到 CPU时间片,也就是使用权,才可以执行指令。那么Java是如何对线程进行调用的呢?
    线程有两种调度模型:
    分时调度模型 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
    抢占式调度模型 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,
    优先级高的线程获取的 CPU 时间片相对多一些。
    如何设置和获取线程优先级
    public final int getPriority() //获取线程的优先级
    public final void setPriority(int newPriority)//设置线程的优先级
    线程控制之休眠线程
    sleep(long millis) 线程休眠

    sleep(long millis) 线程休眠

    加入线程: public final void join()
    意思就是: 等待该线程执行完毕了以后,其他线程才能再次执行
    注意事项: 在线程启动之后,在调用方法

    四、 多线程程序实现的方式2

    public class MyRunnable implements Runnable{
        @Override
        public void run() {
            //需要线程执行
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
    
    
    -----------------------------------------------------------
    	public class MyTest {
        public static void main(String[] args) {
          MyRunnable myRunnable = new MyRunnable();
            Thread th = new Thread(myRunnable);
            th.start();
    
            new MyThread().start();
        }
    }
    ---------------------------------------------
    
    

    五、 多线程程序实现的方式3

    A:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
    B:执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。 FutureTask 是 Future 接口的实现类

    实现步骤
    1.创建一个类实现Callable 接口
    2.创建一个FutureTask类将Callable接口的子类对象作为参数传进去
    3.创建Thread类,将FutureTask对象作为参数传进去
    4.开启线程

    public class MyCallable implements Callable<Integer> {
        //call方法就是线程要执行的方法
        @Override
        public Integer call() throws Exception {
            System.out.println("线程执行了");
            int sum=0;
            for (int i = 1; i <= 100; i++) {
                sum+=i;
            }
            return sum;
        }
    }
    ------------------------------------------------
    public class MyTest {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //创建线程的方式3
            MyCallable myCallable = new MyCallable();
            FutureTask<Integer> task = new FutureTask<>(myCallable);
            Thread thread = new Thread(task);
            thread.start();
            //线程执行完之后,可以获取结果
            Integer integer = task.get();
            System.out.println(integer);
        }
    }
    
    

    八、 实现Runnable接口的方式卖电影票

    案例演示:

    public class MyRunnable implements Runnable{
    
        static int piao = 100;
        @Override
        public void run() {
    
            while (true) {
                if (piao > 1) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "正在出售" + (piao--) + "张票");
                }
            }
        }
    }
    ---------------------------------------------------------------------
    public class MyTest {
        public static void main(String[] args) {
            //A:
            //案例演示
            //需求:某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,
            //请设计一个程序模拟该电影院售票。
            MyRunnable myRunnable1 = new MyRunnable();
            Thread th1 = new Thread(myRunnable1);
            Thread th2 = new Thread(myRunnable1);
            Thread th3 = new Thread(myRunnable1);
            th1.setName("窗口1");
            th2.setName("窗口2");
            th3.setName("窗口3");
            th1.start();
            th2.start();
            th3.start();
        }
    }
    
    
    

    八、 同步代码块的方式解决线程安全问题

    public class MyRunnable implements Runnable {
        static int piao = 100;
        static Object obj = new Object();
        int i=1;
        @Override
        public void run() {
    
                while (true) {
                    //我们在实际网上购票时,会有一些网络延迟,我们可以使用休眠来模拟一下
                    //剩余最后两张票
                    //th1 th2 th3
                    if(i%2==0){
                        //同步代码使用任意对象,作为锁
                        synchronized (MyRunnable.class) { //锁 ,其实就是一个任意对象,多个线程要共享一把锁
                            if (piao >= 1) {
                                try {
                                    Thread.sleep(10);//模拟网络延迟 th1
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
                            }
                        }
                    }else{
                        cellPiao2();
                    }
                    i++;
                    //释放锁
                }
        }
        ---------------------------------
        public class MyTest {
        public static void main(String[] args) {
                MyRunnable myRunnable1 = new MyRunnable();
            Thread th1 = new Thread(myRunnable1);
            Thread th2 = new Thread(myRunnable1);
            Thread th3 = new Thread(myRunnable1);
            th1.setName("窗口1");
            th2.setName("窗口2");
            th3.setName("窗口3");
            th1.start();
            th2.start();
            th3.start();
            }
       }
    

    九、 死锁问题概述和使用

    概述
    如果出现了同步嵌套,就容易产生死锁问题
    是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象
    同步代码块的嵌套案例
    死锁: 两个或者两个以上的线程,在抢占CPU的执行权的时候,都处于等待状态
    举例: 中国人和美国人一起吃饭
    中国人使用的筷子
    美国人使用的刀和叉
    中国人获取到了美国人的刀
    美国人获取到了中国人的一根筷子

    案例演示:
    注意事项: //同步代码块,用的锁对象,是任意锁对象
    //同步方法用的锁对象是this
    //静态同步方法用的锁对象是 字节码类型

    public class MyRunnable implements Runnable {
        static int piao = 100;
        static Object obj = new Object();
        int i=1;
        @Override
        public void run() {
                while (true) {
                     //cellPiao();
                    cellPiao2();
                }
        }
        //方法上加有一个synchronized关键字我们叫做同步方法
        //同步方法使用的所对象不是任意对象,他用的锁是this
        private synchronized void cellPiao() {
                if (piao >= 1) {
                    try {
                        Thread.sleep(20);//模拟网络延迟 th1
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
                }
        }
        //静态同步方法使用的锁对象,不是任意对象,他用的锁是,当前类的 字节码类型
        private synchronized static void cellPiao2() {
            if (piao >= 1) {
                try {
                    Thread.sleep(20);//模拟网络延迟 th1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售" + (piao--) + "张票");
            }
        }
    }
    ------------------------------------------------
    public class MyTest {
        public static void main(String[] args) {
            MyRunnable myRunnable1 = new MyRunnable();
            Thread th1 = new Thread(myRunnable1);
            Thread th2 = new Thread(myRunnable1);
            Thread th3 = new Thread(myRunnable1);
            th1.setName("窗口1");
            th2.setName("窗口2");
            th3.setName("窗口3");
            th1.start();
            th2.start();
            th3.start();
        }
    }
    
    
    展开全文
  • 多线程三种构造方法

    2019-12-11 20:23:20
    注意:很多线程是模拟出来,真正的多线程是指有多个CPU,即多核,比如我们服务器。 一个CPU情况下,(在同一个时间点)CPU只能执行一个线程,因为切换很快,所以就造成了同时执行错觉 多线程三种构建方式...

    Java多线程(入门)

    Java说起线程想到的肯定是程序,他们的关系为: 程序——————>进程——————>线程

    注意:很多线程是模拟出来的,真正的多线程是指有多个CPU,即多核,比如我们的服务器。
    一个CPU的情况下,(在同一个时间点)CPU只能执行一个线程,因为切换的很快,所以就造成了同时执行的错觉

    多线程三种构建方式:

    Thread class——>继承Thread类(重点)
    Runnable接口——>实现Runnable接口(重点)
    Callable接口——>实现Callable接口(了解)

    接下来我将一一讲解三种构建方法体

    1.Thread构建方法:
    上代码:

    package com;
    
    //创建线程方式一:继承Thread类,重写run()方法,调用stort开启线程
    public class demo01 extends Thread{
    	@Override
    	public void run() {
    		//run方法线程体
    		for(int i=0; i<20; i++){
    			System.out.println("我正在学习Thread——>"+i);
    		}
    	}
    	public static void main(String[] args) {
    		//main线程,主线程
    		
    		//创建一个线程对象
    		demo01 testThread1=new demo01();
    		
    		//调用start()方法
    		testThread1.start();
    		//testThread.run();   run方法表示先运行"("我正在学习Thread——>"+i)",而start方法表示同时运行
    		
    		for(int i=0;i<20;i++){
    			System.out.println("我在学习多线程——>"+i);
    		}
    	}
    
    }
    
    

    2.Runnable构建方法:
    上代码:

    package com;
    
    //创建线程方式一:实现Runnable接口,重写run()方法,执行线程需要丢入Runnable
    public class demo02 implements Runnable{
    	@Override
    	public void run() {
    		//run方法线程体
    		for(int i=0; i<20; i++){
    			System.out.println("我正在学习Thread——>"+i);
    		}
    	}
    	public static void main(String[] args) {	
    		//创建Runnable接口的实现类对象
    		demo02 testThread1=new demo02();
    		
    		//创建线程对象,通过线程对象来开启我们的线程,代理
    		new Thread(testThread1).start();
    		
    		for(int i=0;i<20;i++){
    			System.out.println("我在学习多线程——>"+i);
    		}
    	}
    
    }
    
    

    总结:

    继承Thread类
    1.子类继承Thread类具备多线程能力
    2.启动线程:子类对象.start()
    注意:不建议使用,避免OOP单继承局限性

    实现Runnable接口
    1.实现接口Runnable具备多线程能力
    2.启动线程:传入目标对线——Thread对象.start()
    3.推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

    展开全文
  • Java中Thread类是构造线程的一个关键类,正确创建一个线程,意味着如何构造一个正确的线程对象,因此对线程对象的构造就不得不对Thread类构造函数源码进行分析,以下是本人的一些拙见,若有不对之处,望各位大佬勿喷...

    Java中Thread类是构造线程的一个关键类,正确创建一个线程,意味着如何构造一个正确的线程对象,因此对线程对象的构造就不得不对Thread类构造函数源码进行分析,以下是本人的一些拙见,若有不对之处,望各位大佬勿喷!

    首先我们来看一下Thread类源码中的构造函数:

    乍一看有8个被public修饰的和1个被default修饰的构造函数,一些javaer不禁感叹这我哪儿记得住啊!不要急,我们从源码中可以看到每个构造函数调用了一个init方法,所以我们了解Thread构造方法的根源就查看init方法是如何来实现的就行了,看到这儿是不是就开心了许多,接下来我们通过源码来具体看看,init方法具体是如何来实现创建一个Thread对象的。

    在这里我简单的将init方法分为以上9个步骤,然后分别通过分析传入的6个参数进行源码分析

    首先来看第一步,name也就是线程名字,当调用init方法时,他会首先判断name是否传入为空,当为空的时候他会报空指针异常,但是如果我们采用第一个Thread构造方法的时候,他并没有传入任何参数,为什么他不会报错呢,原因在于当未传入任何参数时调用init方法,它会调用nextThreadNum()方法自动为其生成一个线程名,从源码中看到这个自动生成的线程名是Thread-xx的格式,并且nextThreadNum()是被synchronized关键字修饰的,所以是线程安全的,不会引发多个线程生成线程名字混乱的情况。当然了,如果我们自己传入一个线程名,那么我们创建的线程名就是给定的名字。

    总结一下第一步:当用户传入线程名时,当前创建的线程就是给定的名字,如果用户不单独传入,则在init()方法中会调用nextThreadNum()方法自动为其生成一个格式为Thread-xx的线程名,并且nextThreadNum()方法被synchronized修饰,生成的线程名是线程安全的。这样保证了调用init()方法时,不会发生线程名为空而引发空指针异常的情况。

    接下来看看第二步:进入第二步会首先通过你调用currentThread()方法获取创建当前线程的父线程,通过源码不难发现,该方法是被native修饰的,底层通过c++实现,这里就不做过多介绍,我们只需知道,通过该方法获取当前线程的父线程即可。接下来会获取一个安全管理器对象,但是这些都不是主要的,我们重点来看一下传入的线程组参数g,他会首先判断是否传入了线程组参数g,如果为空会继续通过刚才的安全管理器对象去获取线程组,最后如果还是没有线程组对象,他会默认创建该线程的父线程其归属的线程组,即子线程和父线程在同一个线程组中。

    以下做一个简单的例子,便于大家理解,当未传入ThreadGroup对象时,当前创建该线程的父线程是main,,当前线程组就是当前创建的线程和父线程main,当然这里说的不全对,因为还存在一些守护线程,这里不做过多的介绍。

    总结一下第二步:当未传入ThreadGroup对象时,会首先在安全管理器中去获取当前线程组,如果没有获取到,会将创建该线程的父线程归属到和子线程相同的线程组中。

    第三四步是做一下安全检查,不必去深究。

    接下来看一下第五步:

    第五步,线程组g调用的addUnstarted()方法,在源码中注释到其作用是增加线程组中未启动线程的计数。未启动的线程不会添加到线程组中,这样如果它们从未启动过,就可以收集它们,但是必须对它们进行计数,以便包含未启动线程的守护线程组不会被销毁。接下来就是获取线程组属性,isDaemon()判断是否是守护进程,getPriority()获取线程的优先级。

    第六步还是做一些安全的检查,第七步在源码中判断acc时调用的AccessController.getContext()的方法是说当前线程继承的AccessControlContext和任何有限的权限范围,会将其放置在AccessControlContext对象中。然后可以在以后的某个线程中检查该上下文。

    第八步中target是一个Runnable ,Runnable 接口中只有一个run方法,具体当前线程进行什么逻辑操作都是需要根据我们自己的需要实现Runnable 接口进行覆写run()方法的。回到源码中来,Thread是实现了Runnable接口,在调用run()方法时会判断当前传入的参数target是否是空,如果是空或者没有覆写Thread中run()方法,该线程将不会做出任何反应,如果传递了Runnable接口的实例,或者覆写了run()方法,则会执行覆写的run()方法的逻辑单元。

    通过第八步,在这里说一下run()方法和start()方法之间的关系,很多朋友会问,为什么调用了run()方法还要调用start()方法呢?因为从源码中不难发现,Thread是一个类,它继承了Runnable 接口,当实例化Thead后,它实现了run(),所以run()方法仅仅只是一个被覆写了的普通方法,并没有任何特殊之处,如果没有调用start(),run()方法只是在主线程中进行,没有创建任何新线程。

    看下面的start()方法源码,调用start()方法后,JVM会调用创建线程的run()方法,在源码中没有体现,是通过底层调用本地方法start0()进行实现的,并且同一个线程不能被同时start()两次,否则会报IllegalThreadStateException异常。

    总结一下第八步:当我们创建线程时一定要传递Runnable接口的实例或者覆写run()方法,如果什么都没操作,该线程不会进行任何操作。创建一个线程需要调用start()方法才能真正的使得该线程起作用,如果是单核cup的话,一旦启动start()方法,该线程并不能保证会立即执行,只是处于一个可执行状态,因为,当前线程需要和其他线程抢夺时间片,当获得时间片后,他才会真正的执行。

    第九步就会涉及到JVM一些知识,stackSize指的是当前线程所需要的堆栈的大小,如果没有指定会默认忽略此参数。方法介绍中还指出,该参数在一些平台是有效的,一些平台则无效。最后就是获取线程的一个id,源码中也可以看到该方法也是被synchronized修饰的,因此获取到的线程id是线程安全的。

    说到这里,创建一个简单的线程就基本搞定了!主要的就是明白Thread类构造方法的参数是什么含义,具有什么作用,能够帮助我们更加深刻的理解一个线程的创建思路。

    最后,鉴于本人第一次写一些自己的认识,希望对有需要的朋友有所帮助,如若有不正确的地方,还望各位大佬在评论区留言,我将会不断地去提高自己,尽最大努力写出一些更好的文章。

     

    展开全文
  • 先定一个类,既有构造函数又有类方法: public class WriteNumber { /// <summary> /// 构造函数 /// </summary> public WriteNumber() { Console.Wr...

    先定一个类,既有构造函数又有类方法:

    public class WriteNumber
        {
            /// <summary>
            /// 构造函数
            /// </summary>
            public WriteNumber()
            {
                Console.WriteLine("WriteNumber-----begin");
                Console.WriteLine("Name:" + Thread.CurrentThread.Name);
                Console.WriteLine("WriteNumber-----end");
            }
    
            /// <summary>
            /// 类方法
            /// </summary>
            public void WriteString()
            {
                Console.WriteLine("WriteString-----begin");
                Console.WriteLine("Name:" + Thread.CurrentThread.Name);
                Console.WriteLine("WriteString-----end");
            }
        }

     

    用多线程运行:

    public static void Main(string[] args)
            {
                try
                {
                    Thread.CurrentThread.Name = "main";   //定义当前线程名称
                    WriteNumber writenumber = new WriteNumber();
                    Thread t1 = new Thread(new ThreadStart(writenumber.WriteString));
                    t1.Name = "000"; //定义t1线程名称
                    t1.Start();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                Console.ReadLine();
            }

    得出的结果:

    转载于:https://www.cnblogs.com/whtydn/p/10286376.html

    展开全文
  • 有时候,系统需要处理非常的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长。而且当线程数量太时,...
  • 】Thread类的构造方法与常用方法 基础概念 线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行个执行线程。 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以...
  • Java多线程-线程池ThreadPoolExecutor构造方法和规则

    万次阅读 多人点赞 2017-05-03 17:15:37
    http://blog.csdn.net/qq_25806863原文地址 http://blog.csdn.net/qq_25806863/article/details/71126867有时候,系统需要处理非常的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行...
  • 文章目录Java多线程相关知识【2】--Thread的构造方法一、Thread()二、Thread(Runnable target)三、Thread(String name)四、Thread(Runnable target, String name)五、Thread(ThreadGroup group, Runnable target)六...
  • 多线程的使用 t.start 将线程放到就绪队列中,当线程被分配到CPU资源时,才会运行起来。 该线程被调度下来的5中情况: 1:被高优先级抢占 2:执行结束 3:等待IO 4:主动放弃 5:时间片耗尽了 public class Main { ...
  • 首先,我们知道线程其实就是每一个进程里面有多个执行单元同时执行。(就像电脑上每一个软件被打开时,就相当于正在运行一个进程,而这个进程...下面是单线程的代码,通过两个代码来对比多线程与单线程的区别 public cl
  • 多线程的操作方法

    2020-04-04 21:40:58
    多线程操作方法在Thread类中定义. ...*构造方法:public Thread​(Runnable target,String name) *设置名字:public final void setName​(String name) *取得名字:public final String getNam...
  • 有时候,系统需要处理非常的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长。而且当线程数量太时,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,176
精华内容 2,070
关键字:

多线程的构造方法