美文网首页
Java之 线程(一)

Java之 线程(一)

作者: 五月笙 | 来源:发表于2021-09-07 10:29 被阅读0次

定义

什么是进程?

维基百科:进程
百度百科:进程

什么是线程?

维基百科:线程
百度百科:线程

什么是并发?
什么是并行?

参考:并发和并行的区别

线程

创建线程

  1. 拓展java.lang.Thread
    子类中重写run()方法
  2. 实现java.lang.Runnable
package thread;

public class RunnalbleImpl implements Runnable {

    private String tip;

    public RunnalbleImpl(String tip) {
        this.tip = tip;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100000; k++) {
                System.out.println(tip + ":" + i);
            }
        }
    }
}

执行代码

Thread thread1 = new Thread(new RunnalbleImpl("我是=========="));
Thread thread2 = new Thread(new RunnalbleImpl("他是++++++++++"));
thread1.start();
thread2.start();

结果可以看到两个线程执行任务是${并行/并发}执行的

public class TestThread extends Thread {

    public TestThread(String tip) {
        super(tip);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100000; k++) {
                System.out.println(this.getName() + ":" + i);
            }
        }
    }
}

执行

Thread thread1 = new TestThread("第一个任务");
Thread thread2 = new TestThread("第二个任务");
thread1.start();
thread2.start();

问题

线程可以设置名字,在源码中可以查看到

  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);
        }
    }

实际上一次只能运行一个线程,JVM线程调度程序决定实际运行哪个处于可运行状态的线程,众多可运行线程中的某一个会被选中做为当前线程。可运行线程被选择运行的顺序是没有保障的。

Thread thread1 = new TestThread("第一个任务");
Thread thread2 = new TestThread("第二个任务");
thread1.start();
thread2.start();
System.out.println("=============================================");

如何让线程暂停一下

public class TestThread extends Thread {

    public TestThread(String tip) {
        super(tip);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100000; k++) {
                if (k == 50000) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(this.getName() + ":" + i);
            }
        }
    }
}

想要先执行一部分东西,后等待其他的执行完成后做处理,就需要加上sleep()处理
如果执行下面代码会发生什么事情


    Thread thread1 = new TestThread("第一个任务");
    thread1.start();
    System.out.println("============================================");

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100; k++) {
                System.out.println(this.getName() + ":" + i);
                if (k == 5 && i == 3) {
                    try {
                        Thread.sleep(2000);
                        System.out.println("thread sleep =====");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

什么时候会提前执行主线程的代码?

线程状态
  • 新状态:线程对象已经创建,还没有在其上调用start()方法。
  • 可运行状态:有资格运行,但是还没有选定为运行状态。
  • 运行状态:线程调度程序从可运行池中选取一个线程作为当前运行状态。
  • 等待/阻塞/睡眠状态:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。
  • 死亡态:当线程的run()方法完成时就认为它死去。
线程的优先级

    /**
     * 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;
    /**
     * @see        #getPriority
     * @see        #checkAccess()
     * @see        #getThreadGroup()
     * @see        #MAX_PRIORITY
     * @see        #MIN_PRIORITY
     * @see        ThreadGroup#getMaxPriority()
     */
    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);
        }
    }

在了解的源码的优先级后去执行如下代码

public class Main {

    public static void main(String[] args) {
        String code = Crypt.mapEncode(1878, 6);
        System.out.println(code);
        Thread thread1 = new TestThread("第一个任务");
        Thread thread2 = new TestThread("第二个任务");
        thread2.setPriority(Thread.MAX_PRIORITY);
        thread1.start();
        thread2.start();
        System.out.println("============================================");
    }
}

当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。

yield()

暂停当前正在执行的线程对象,并执行其他线程

Thread thread1 = new TestThread("第一个任务");
Thread thread2 = new Thread(new RunnalbleImpl("第二个任务"));
thread1.start();
thread2.start();
System.out.println("============================================");

/** 第一个线程 **/

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100; k++) {
                System.out.println(this.getName() + ":" + i);
                if (i == 3 && k == 50){
                    Thread.yield();
                }
            }
        }
    }

/** 第二个线程 **/
@Override
public void run() {
    for (int i = 0; i < 5; i++) {
        for (long k = 0; k < 100; k++) {
            System.out.println(tip + ":" + i);
        }
    }
}

如果把第二个线程的k值放大,会有什么不同的影响?

使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。因此yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

join

Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。

相关文章

网友评论

      本文标题:Java之 线程(一)

      本文链接:https://www.haomeiwen.com/subject/zlvmnktx.html