定义
什么是进程?
什么是线程?
什么是并发?
什么是并行?
参考:并发和并行的区别
线程
创建线程
- 拓展java.lang.Thread
子类中重写run()方法 - 实现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不能工作。
网友评论