线程源码

基于jdk1.8

线程设置

使用多线程时,想查看线程名

Thread.currentThread().getName()

如果什么设置都没做,主线程叫main,其他线程叫Thread-*

不适用如何参数进行创建线程时,

    /**
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, null, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     */
    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

nextThreadNum():

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

基于threadInitNumber:线程初始化的数量

线程初始化代码

    /**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

测试

实现Runnable的方式实现多线程

public class MyThread implements Runnable {

    @Override
    public void run() {
        // 打印出当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}
-- main类
public class ThreadDemo {
    public static void main(String[] args) {


        MyThread myThread = new MyThread();

        //带参构造方法给线程起名字
        Thread thread1 = new Thread(myThread, "ndb");
        Thread thread2 = new Thread(myThread, "lalala");


        thread1.start();
        thread2.start();

        // 打印当前线程的名字
        System.out.println(Thread.currentThread().getName());
    }
}

可以通过**setName(String name)**来修改线程的名字

    public final synchronized void setName(String name) {
        checkAccess();
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;
        if (threadStatus != 0) {
            setNativeName(name);
        }
    }
    
    public final void checkAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkAccess(this);
        }
    }
    
    public void checkAccess(Thread t) {
        if (t == null) {
            throw new NullPointerException("thread can't be null");
        }
        if (t.getThreadGroup() == rootGroup) {
            checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION);
        } else {
            // just return
        }
    }

守护线程

特点:

  • 为其他线程服务(垃圾回收线程就是守护线程)
  • 当别的用户线程执行完,虚拟机退出,守护线程就会停止
  • 属于服务线程,没有服务对象,就没必要继续运行

注意点:

  • 在线程启动之前设置守护线程,setDaemon(boolean on)
  • 在使用守护线程时不要访问共享资源,如数据库、文件什么的,它可能在任何时候挂掉
  • 守护线程中产生的新线程也是守护线程

优先级

线程的优先级高低表示线程获取cpu时间片的几率,这个几率是,不确定因素

线程的优先级依赖于操作系统

在Java中提供10个不同的优先级,默认5级

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

实现

    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
  • 如果存在线程组,那么该线程的优先级不能线程组高,如果比线程组高,该线程的优先级为线程组的最大优先级
  • setPriority0是一个本地(navite)的方法,natnaive修饰的方法不由Java实现,使用c/c++实现
 private natnaive void setPriority0(int newPriority);

线程的生命周期

sleep
调用sleep方法会计时等待,等待时间到,进入就绪状态而非运行状态

    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;
  • 受精确的时间限制(单位毫秒)

yield方法
调用yield方法先让别的线程执行,但不确保真正让出(我有空,可以的话,可以让你们先执行)

    /**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static native void yield();

join方法
调用join方法,会等待该线程执行完毕后才能执行别的线程

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }

/**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

wait方法是在Object上定义的,是native本地方法,所以就看不了了
wait方法实际是它也是计时等待(如果带时间参数)的一种

interrupt方法
线程中断在之前的版本有stop方法,但是被设置过时了。现在已经没有强制线程终止的方法
由于stop方法可以让一个线程A终止另一个线程B

  • 被终止的线程会立即释放锁,这可能会让对象处于不一致的状态
  • 线程A也不知道线程B什么时候能够被终止调,万一线程B还在处理运行计算阶段,线程A调用stop方法将线程B终止,那就很无辜了
    总而言之,stop方法太暴力,不安全,所以被设置过时了

一般使用interrupt来请求终止线程

  • 要注意的是:interrupt不会真正停止一个线程,只是告诉这个线程一个信号,它应该结束了
  • Java设计者实际上是想线程自己来终止,通过上面的信号,就可以判断处理什么业务
  • 具体到底中断还是继续处理什么业务应该由被通知的线程自己处理

范例代码

Thread t1 = new Thread( new Runnable(){
    public void run(){
        // 若未发生中断,就正常执行任务
        while(!Thread.currentThread.isInterrupted()){
            // 正常任务代码……
        }
        // 中断的处理代码……
        doSomething();
    }
} ).start();

再次说明:调用interrupt()并不是要真正终止掉当前线程,仅仅是设置了一个中断标志。这个中断标志可以给我们用来判断什么时候该干什么活!什么时候中断由我们自己来决定,这样就可以安全地终止线程了!

/**
     * Interrupts this thread. // 中断当前线程
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown. // 只能自己调用中断的方法,不然会抛异常
     *
     * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
     *
     * <p> If this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel InterruptibleChannel}
     * then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     *
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

interrupt方法不会对线程状态造成影响,它仅仅设置一个标志位

interrupt线程中断还有两个方法用于检测线程是否被中断

  • interrupted()----会清除中断标志为
  • isInterrupted() ----不会清除

如果阻塞线程调用interrupt方法,会抛出异常,设置标志位false,同时线程退出阻塞

范例

public class Main {
    /**
     * @param args
     */
    public static void main(String[] args) {
        Main main = new Main();

        // 创建线程并启动
        Thread t = new Thread(main.runnable);
        System.out.println("This is main ");
        t.start();

        try {

            // 在 main线程睡个3秒钟
            Thread.sleep(3000);
            // 在mian线程中睡了3秒,因此执行新的进程
        } catch (InterruptedException e) {
            System.out.println("In main");
            e.printStackTrace();
        }

        // 设置中断
        t.interrupt();
    }

    Runnable runnable = () -> {
        int i = 0;
        try {
            while (i < 1000) {

                // 睡个半秒钟我们再执行
                Thread.sleep(500);

                System.out.println(i++);
            }
        } catch (InterruptedException e) {


            // 判断该阻塞线程是否还在
            System.out.println(Thread.currentThread().isAlive());

            // 判断该线程的中断标志位状态
            System.out.println(Thread.currentThread().isInterrupted());

            System.out.println("In Runnable");
            e.printStackTrace();
        }
    };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java多线程机制: 例子 1 public class Example1 { static Lefthand left;static Righthand right; public static void main(String args[]) { left=new Lefthand(); //创建两个线程。 right=new Righthand(); left.start(); right.start(); } } class Lefthand extends Thread { public void run() { for(int I=0;I<=5;I++) { System.out.println("I am a student"); try{sleep(500);} catch(InterruptedException e){} } } } class Righthand extends Thread { public void run() { for(int I=0;I<=5;I++) { System.out.println("I am oookkk"); try{sleep(300);} catch(InterruptedException e){} } } } 在上述例子中,我们在main主线程中创建了两个新的线程lefthand和righthand。当lefthand调用start()开始运行时,类Lefthand中的run()将自动被执行。 我们来分析一下上面程序的输出结果。Left线程首先开始执行,这时Lefthand类中的run方法开始执行,输出”I am a student”后,left主动“休息”500毫秒,让出了CPU。这时正在排队等待CPU的right线程的run方法马上被执行,输出“I am ookk”,right在主动让出CPU300毫秒后又来排队等待CPU服务,这时right发现left还没有“醒来”,即没有来排队抢占CPU,因此left的run方法被执行,又输出“I am oookkk“… …。程序的执行结果是: E:\dd>java Example1 I am student I am oookkk I am oookkk I am student I am oookkk I am oookkk I am student I am oookkk I am student I am oookkk I am student I am student 2.实现Runnable接口 例子 2 import java.applet.*; import java.awt.*; public class Example2 extends java.applet.Applet implements Runnable { Thread circleThread; public void start() { if (circleThread==null) { circleThread=new Thread(this); circleThread.start(); } } public void run() { while(circleThread !=null) { repaint(); try{ circleThread.sleep(1000); } catch(InterruptedException e){} } } public void paint(Graphics g) { double i=Math.random(); if(i<0.5) g.setColor(Color.red); else g.setColor(Color.blue); g.fillOval(100,100,(int)(100*i),(int)(100*i)); } public void stop() { circleThread.yield(); circleThread=null; } } 在上述例子2中,我们在小程序这个主线程中用构造方法Thread(this)创建了一个新的线程。This代表着小程序作为这个新的线程的目标对象,因此我们的小程序必须为这个新创建的线程实现Runnable接口,即小程序利用Runnable接口为其中创建的这个新线程提供run()方法,给出该线程的操作。 首先,在小程序的start()方法中构造了一个名为circleThread的线程并调用线程类的start()方法来启动这一线程,即在小程序的主线程中又开始了一个线程:circleThread。下面的语句建立了一个新的线程: circlethread =new Thread(this); 其中this作为该线程的目标对象,它必须实现Runnable接口。线程被启动以后,自动调用目标对象的run()方法,除非线程被停止。在run()方法的第十一中,Applet重绘本身,然后睡眠1秒,同时要捕获异常事件并进行处理。 如果你离开这一页,程序将调用stop()方法,将线程置空。当你返回时,又会创建一个新的线程。在具体应用中,采用哪种方法来构造线程体要视具体情况而定。通常,当一个新的线程已继承了另一个类,而想在该线程中创建一个新的线程时,就应该用第二种方法来构造,即实现Rennable接口。 需要理解的是,我们的小应用程序实际上是浏览器的一个线程,这个线程由浏览器启动执行,浏览器自动调用执行小程中的init()、start()方法等。因此我们要创建一个新的线程最好把新线程的启动放在小程序的start()方法中。 下面的例子3是一个应用程序,这个应用程序在创建窗口的同时又创建了一个新的线程,该线程负责让窗口中的一个按钮改变它的大小。 例子 3 import java.awt.*; import java.awt.event.*; public class Example3 { public static void main(String args[]) { Mywin win=new Mywin(); win.pack(); } } class Mywin extends Frame implements Runnable { Button b=new Button("ok"); int x=5; Thread bird=null; Mywin() { setBounds(100,100,120,120); setLayout(new FlowLayout()); setVisible(true); add(b); b.setBackground(Color.green); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); bird=new Thread(this); //创建一个新的线程,窗口做目标对象, //替线程bird实现接口Runnable。 bird.start(); //在创建窗口时又开始了线程dird. } public void run() { while(true) { x=x+1; if(x>100) x=5; b.setBounds(40,40,x,x); try{bird.sleep(200);} catch(InterruptedException e){} } } } 滚动字幕线程。 例子 4 import java.applet.*; import java.awt.*; public class Example4 extends java.applet.Applet implements Runnable { int x=0; Thread Scrollwords=null; public void init() { setBackground(Color.cyan); setForeground(Color.red); setFont(new Font("TimesRoman",Font.BOLD,18)); } public void start() { if(Scrollwords==null) { Scrollwords=new Thread(this); Scrollwords.start(); } } public void run() { while (Scrollwords!=null) { x=x+5; if(x>500) x=0; repaint(); try{Scrollwords.sleep(80);} catch(InterruptedException e){} } } public void paint(Graphics g) { g.drawString("欢 迎 使 用 字 典 ",x ,80); } public void stop() { Scrollwords.yield(); Scrollwords=null; } } 带滚动字幕的小字典。 例子 5 import java.applet.*; import java.awt.*; import java.awt.event.*; public class Example5 extends Applet implements ActionListener,Runnable { TextField text1,text2; int x=0; Thread Scrollwords=null; public void init() { setBackground(Color.cyan); setForeground(Color.red); setFont(new Font("TimesRoman",Font.BOLD,18)); text1=new TextField(10); text2=new TextField(10); add(new Label("输入一个英文单词:")); add(text1); add(new Label("汉语意思:")); add(text2); text1.addActionListener(this); } public void start() { if(Scrollwords==null) { Scrollwords=new Thread(this); Scrollwords.start(); } } public void run() { while (Scrollwords!=null) { x=x+5; if(x>500) x=0; repaint(); try{Scrollwords.sleep(80);} catch(InterruptedException e){} } } public void paint(Graphics g) { g.drawString("欢 迎 使 用 字 典 ",x ,120); } public void stop() { Scrollwords.yield(); Scrollwords=null; } public void actionPerformed(ActionEvent e) { if((e.getSource()==text1)&&(text1.getText().equals("boy"))) { text2.setText("男孩"); } else if((e.getSource()==text1)&&(text1.getText().equals("sun"))) { text2.setText("太阳"); } else { text2.setText("没有该单词"); } } } 下面是一个左手画圆右手画方的例子。我们在主线程中创建了两个线程:left、right,其中一个负责画圆,另一个负责画方。在这个例子中我们使用了容器类的方法getGraphics()来获取一个Graphics对象(可以理解为一个画笔)。 例子 6 (效果如图1所示) 图1 双线程绘画程序 import java.applet.*; import java.awt.*; import java.awt.event.*; public class Example6 extends Applet implements Runnable { Thread left,right; Graphics mypen; int x,y; public void init() { left=new Thread(this); right=new Thread(this); x=10; y=10; mypen=getGraphics(); } public void start() { left.start(); right.start(); } public void run() { while(true) if (Thread.currentThread()==left) { x=x+1; if(x>240) x=10; mypen.setColor(Color.blue); mypen.clearRect(10,10,300,100); mypen.drawRect(10+x,10,50,50); try{left.sleep(60);} catch(InterruptedException e){} } else if(Thread.currentThread()==right) { y=y+1; if(y>240) y=10; mypen.setColor(Color.red); mypen.clearRect(10,110,300,100); mypen.drawOval(10+y,110,50,50); try{right.sleep(60);} catch(InterruptedException e){} } } public void stop() { left=null; right=null; } }
### 回答1: 抱歉,我可能误解了您的问题。Visual Studio 并不是线程的源代码,而是一个集成开发环境 (IDE),它提供了一种方便的方式来开发、测试和调试多线程应用程序。 如果您想了解有关线程的源代码,您可以查看操作系统或编程语言的相关文档和源代码,比如 Windows 操作系统提供了一些 API 来创建和管理线程,例如 CreateThread 函数。C++11 也提供了一些线程相关的类和函数,例如 std::thread 和 std::mutex。 此外,还有一些第三方库,如 Boost 和 Pthreads,提供了丰富的线程支持。 请让我知道如果您有任何进一步的问题。 ### 回答2: Visual Studio 是一款集成开发环境(IDE),可用于各种编程语言的开发,包括C++语言。在Visual Studio中,我们可以利用其提供的线程源码来实现多线程的编程。 在C++中,我们可以使用Windows API中的线程函数来创建和操纵线程,例如CreateThread函数。而在Visual Studio的线程源码中,它提供了一些封装函数和类来简化线程的创建和管理。 其中,最常用的类是std::thread。我们可以使用std::thread类来创建一个线程,并指定线程执行的函数。例如,以下代码示例创建了一个线程,执行一个名为myFunction的函数: ``` void myFunction() { // 线程执行的代码 } int main() { std::thread myThread(myFunction); // 创建线程 myThread.join(); // 等待线程执行完毕 return 0; } ``` 在这个示例中,我们首先定义了一个名为myFunction的函数,该函数是线程实际执行的代码。然后,通过std::thread类创建了一个名为myThread的线程,并将myFunction函数作为参数传递给它。最后,我们使用myThread.join()等待线程执行完毕。 除了std::thread类,Visual Studio还提供了其他一些类和函数来管理线程,例如std::mutex、std::condition_variable等,用于实现线程间的同步和通信。 总结来说,Visual Studio的线程源码提供了一些简单易用的类和函数来创建和管理线程。通过这些工具,我们可以更方便地实现多线程的编程,提高程序的并发性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值