线程学习笔记(一)

一、引入多线程

请看上图中的代码执行流程,就可以大概的理解多线程。说到多线程就一定会联系到单线程,所谓单线程就是程序只有一条执行路径。相反,多线程就是程序有多条执行路径。

二、进程的概述

1.要想了解多线程,必须先了解线程。了解线程就必须先了解进程。因为线程依赖于进程。

2.什么是进程:就是正在运行中的程序。进程是系统进行资源分配和调度的独立单位,每一个进程都有自己独立的内存空间和系统资源。

3.多进程的意义:在同一时间段内可以执行多个任务,极大的提高了CPU的使用率。单核的CPU在某一时刻只能执行一个任务。

三、线程的概述

1.什么是线程:在同一个进程中又可以执行多个任务,而这每一个任务可以看成一个线程。线程是程序执行路径和执行单元,是程序使用CPU的基本单元。

2.多线程的意义:不是提高程序的执行速度的,而是提高应用程序的使用率的。程序的执行其实都在抢CPU资源和CPU的执行权。多个进程都在争夺CPU这一资源,而其中一进程有多个执行路径,抢到这一资源的几率就更高。但线程的执行是由随机性的。

四、并行和并发

并行:逻辑上同时发生,是指在同一时间内同时运行多个程序。

并发:物理上同时发生,是指在同一时间点上同时运行多个程序。

五、Java程序运行原理

执行Java命令就会启动Java虚拟机,启动JVM就等于启动了一个应用程序,也就是启动了一个进程,该进程会自动启动一个主线程。然后,主线程会去调用某个类的main方法,所以main方法时运行在主线程中的。

通过上图,可以看到启动一个Java程序,就会启动一个线程,在该线程中调用main方法。

JVM的启动是多线程的:在运行一个Java程序的时候,在启动主线程的时候,也会启动垃圾回收线程,否则会出现内存溢出。

六、创建线程的方式

1. 继承java.lang.Thread类,重写run()方法,创建线程对象并启动线程。

package com.jd;

/**
 * Created by shifeifei on 2015/8/12.
 */
public class MyThread extends Thread {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        /**
         * run():仅仅是封装了线程执行的代码,直接调用就是普通方法
         * start():首先启动了线程,然后由JVM去调用run()方法
         */
        t.start();

        /**
         *要启动多个线程,必须先创建多个线程对象,再调start()方法
         */
        MyThread t2 = new MyThread();
        t2.start();
    }

    @Override
    public void run() {
        for(int i=0;i<200;i++) {
            System.out.println("当前线程是:"+ this.getName() + " " + i);
        }
    }
}

 

获取线程名称的方法是:public final String getName(),该方法返回的线程名称形式是:Thread-?(?代表0、1、2等自然数),为什么会是这种形式呢?我们开源码解析:

由于MyThread类继承与Thread类,进入到Thread类,我们可以看到如下代码:

    private static int threadInitNumber;

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    private char    name[];

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        this.name = name.toCharArray();
    }

    public final String getName() {
        return String.valueOf(name);
    }

 

即在创建线程对象的时候,就调用init()方法。

既然能够获取线程的名称,我们也能够设置线程的名称,常用的方式有两种:调用public final void setName(String name)和

public Thread(String name)
  • 线程调度

   (1) 分时调度模型:所有线程轮流使用CPU的执行权,平均分配每个线程占用CPU的时间片。

   (2) 抢占式调度模型:优先级高的线程优先使用CPU执行权,如果线程的优先级相同,就会随机选择一个执行,优先级高的线程获取CPU使用权多一些。

   (3) Java中使用抢占式调度模型。

    线程的优先是从1 - 10,默认的优先级为 5.

    1.获取线程的优先级:public final int getPriority()

    2.设置线程的优先级:public final void setPriority(int newPriority)

package com.jd;

/**
 * Created by shifeifei on 2015/8/13.
 * */
public class ThreadPriority extends Thread {
    @Override
    public void run() {
        for(int i=0;i<100;i++) {
            System.out.println(this.getName() + " " + i);
        }
    }

    public static void main(String[] args) {
        ThreadPriority t1 = new ThreadPriority();
        ThreadPriority t2 = new ThreadPriority();
        System.out.println(t1.getPriority() + " " + t2.getPriority());
        t1.start();
        t1.setPriority(10);
        t2.start();
        t2.setPriority(1);
    }
}

时间: 2024-11-10 01:15:35

线程学习笔记(一)的相关文章

Java线程学习笔记(二) 线程的异常捕捉

线程异常的捕捉: 正常的情况下,我们在main()方法里是捕捉不到线程的异常的,例如以下代码: public class ExceptionThread implements Runnable{ @Override public void run() { throw new NullPointerException(); } public static void main(String[] args) { ExecutorService executorService = Executors.n

Java线程学习笔记(一)

一.线程的创建方式: 老掉牙的话题了,继承 java.lang.Thread父类或者实现Runnalbe接口,这里就提一句: class Thread implements Runnable Thread也是继承了Runnable接口的,Runnable才是大哥. 重写run(),run()里放的都是具体的业务,包括对线程的具体操作. class Thread1 implements Runnable { int i; Thread1(int i) { this.i = i; } @Overri

【转】linux 用户线程、LWP、内核线程学习笔记

[好文转发---linux 用户线程.LWP.内核线程学习笔记] 在现代操作系统中,进程支持多线程.进程是资源管理的最小单元:而线程是程序执行的最小单元.一个进程的组成实体可以分为两大部分:线程集合资源集.进程中的线程是动态的对象:代表了进程指令的执行.资源,包括地址空间.打开的文件.用户信息等等,由进程内的线程共享. 线程有自己的私有数据:程序计数器,栈空间以及寄存器. Why Thread?(传统单线程进程的缺点) 1. 现实中有很多需要并发处理的任务,如数据库的服务器端.网络服务器.大容量

线程学习笔记

1.什么是线程? 老师说过学好操作系统(Operating System)最重要的三个概念就是文件.虚存和进程了.之前已经学习过进程,因此对于线程的概念就比较好理解了. 进程是一个执行实体,操作系统是以进程为单位分配资源.在一个执行空间内可以用多个小型进程并发来完成不同的任务,这种小型的进程称之为线程.进程是一个比较大的概念,线程是一个比较具体化的小的概念,比如一个进程需要完成这样一个任务,读出用户收到的数据,将这些数据进行排序,再将这些数据输出,这是一个进程要完成的任务,这个进程中可以有三个线

线程学习笔记2

对于文章里面碰到的问题,可能也是我学习1当中出现的问题,新开的线程不管委托与否都在同一个线程里面,所以新线程运行的时候,主窗体也会停住,后来想在新线程中打开窗体的思路来处理,结果碰到下面文章的问题,在多方面的查找和学习后发现有一个办法可以解决它,希望对大家有帮助. private void button7_Click(object sender, EventArgs e) { Thread thread2 = new Thread(threadPro);//创建新线程 thread2.Start

线程学习笔记(二)

5.终止线程 线程退出的方式有3种 1.线程体函数执行结束,用 pthread_create() 函数创建一个新线程的时候会执行一个函数,这个函数就是线程体函数,如果该函数执行完毕,那么线程退出,类似于住进程的 main() 函数返回. 2.线程被另一个线程取消.这种方法类似于一个进程被另一个进程调用kill()函数杀死. 3.线程自行退出,类似于线程调用一个 exit() 函数. Linux系统中使用 pthread_exit(void *rval_ptr) 函数终止线程: 头文件:  #in

线程学习笔记(EventWaitHandler)AutoResetEvent的使用

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication46 { class TwoWaySignaling { //事件等待句柄 static EventWaitHandle _ready = new AutoRese

线程学习笔记 等待句柄和线程池(摘自https://blog.gkarch.com/threading/part2.html#manualresetevent)

//如果你的应用有很多线程,这些线程大部分时间都在阻塞,那么可以通过调用ThreadPool.RegisterWaitForSingleObject来减少资源消耗.这个方法接受一个委托,它会在向等待句柄发信号时执行.当处于等待状态时,它不会浪费线程资源: static ManualResetEvent _starter = new ManualResetEvent (false); public static void Main() { RegisteredWaitHandle reg = Th

lua协程----ngx-lua线程学习笔记

--[[ - @desc lua数据输出 - @param string 字符串 - return string --]] function dump(v) if not __dump then function __dump(v, t, p) local k = p or ""; if type(v) ~= "table" then table.insert(t, k .. " : " .. tostring(v)); else for key

Java线程学习笔记(两) 线程异常处理

线程捕获异常: 情况下,我们在main()方法里是捕捉不到线程的异常的,比例如以下面代码: public class ExceptionThread implements Runnable{ @Override public void run() { throw new NullPointerException(); } public static void main(String[] args) { ExecutorService executorService = Executors.new