Java语言内置多线程支持:

  • 一个Java程序实际上是一个JVM进程
  • JVM用一个主线程来执行main()方法
  • 在main()方法中又可以启动多个线程

1.创建新线程

要启动一个线程,需创建一个线程对象。创建线程对象的方法有3种。

1.1 方法一:使用Thread创建线程

创建MyThread类:

  • 从Thread派生
  • 覆写run()方法
  • 创建MyThread()实例
  • 对这个实例调用start()启动线程
class MyThread extends Thread{
public void run(){
System.out.println("子线程");
}
}
public class Main {
public static void main(String[] args){
Thread t = new MyThread();
t.start();
}
}


疯狂Java示例
```#java
package com.thread;

public class FirstThread extends Thread{

private int i;

public FirstThread(){}

public FirstThread(String name){

super(name);

}

public void run(){

for(;i<10;i++) {

System.out.println(getName()+i);

}

}

public static void main(String[] args) throws InterruptedException{

for(int i=0;i<10;i++){

System.out.println(Thread.currentThread().getName()+i);

if(i==5){

new FirstThread().start();

Thread.sleep(500);

new FirstThread("通过集成Thread创建新线程").start();

        }
Thread.sleep(500);
}
}

}

<img src="https://img2018.cnblogs.com/blog/1418970/201905/1418970-20190528195416006-597594251.png" width="500" />

###    1.2 方法二:使用Runnable接口创建新线程
如果一个类已经从某个类派生,无法从Thread继承:
* 实现Runnable接口
* 覆写run()接口
* 在main()方法中创建Runnable实例
* 创建Thread实例并传入Runnable
* 调用start()启动线程
```#java
class MyThread implements Runnable{
public void run(){
System.out.println("子线程");
}
}
public class Main {
public static void main(String[] args){
Runnable mt = new MyThread();
Thread t = new Thread(mt);
t.start();
}
}

疯狂Java示例

package com.thread;

public class SecondThread implements Runnable{
private int i;
public void run(){
for(;i<10;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量"+i);
}
}
public static void main(String[] args) throws InterruptedException{
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量"+i);
if(i==5){
SecondThread st = new SecondThread();
new Thread(st,"新线程1").start();
Thread.sleep(500);
new Thread(st,"新线程2").start();
Thread.sleep(500);
}
Thread.sleep(500);
}
}
}

1.3 方法三:使用Futrue和Callable创建子线程

实现Callable接口,覆写call()方法。再用Future进行转换

class WithResult implements Callable<Integer>{
@Override
public Integer call() throws Exception {
return 5;
}
}
public class ForZhang {
public static void main(String[] args) throws Exception{
Callable<Integer> th = new WithResult();
FutureTask task = new FutureTask<>(th);
new Thread(task,"有返回值的线程").start();
}
}

示例

package com.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; public class ThirdThread{
public static void main(String[] args) throws InterruptedException{
ThirdThread th = new ThirdThread();
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)()->{
int i=0;
for(;i<10;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量的值"+i);
}
return i;
});
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"循环变量的值"+i);
if(i==5){
new Thread(task,"有返回值的线程").start();
}
Thread.sleep(500);
}
try{
System.out.println("线程task的返回值:"+task.get());
}catch (ExecutionException e){
e.printStackTrace();
}
}
}

class WithResult implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int i=0;
for(;i<10;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量的值"+i);
}
return i;
}
}
public class ThirdThread {
public static void main(String[] args) throws Exception{
Callable<Integer> th = new WithResult();
FutureTask task = new FutureTask<>(th);
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"循环变量的值"+i);
if(i==5){
new Thread(task,"有返回值的线程").start();
}
Thread.sleep(500);
}
try{
System.out.println("线程task的返回值:"+task.get());
}catch (ExecutionException e){
e.printStackTrace();
}
}
}

2.启动线程需要注意的地方

2.1 直接调用run()方法

直接调用run()方法是无效的,相当调用普通的Java的方法,当前线程没有任何的改变,也不会启动新的线程。

class MyThread extends Thread{
public void run(){
System.out.println("当前线程"+Thread.currentThread().getName()+"\tHello");
}
} public class Main {
public static void main(String[] args){
Thread t = new MyThread();
t.run();//直接调用run()方法
Thread t2 = new MyThread();
t2.start();
System.out.println("主线程"+Thread.currentThread().getName());
}
}

start源码

class Thread implements Runnable {
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this); boolean started = false;
try {
start0(); //调用JVM虚拟机内部的start0()方法
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {}
}
} private native void start0(); //native表示JVM虚拟机内部的C代码实现的,不是由Java代码实现的

2.2 新线程和主线程是同时执行

默认情况下,新线程和主线程是同时执行的,由操作系统调度,程序本身无法确认线程的的调度顺序

class HelloThread extends Thread{
String name;
public HelloThread(String name){
this.name = name;
}
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("Hello, " + name + "!");
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
} public class Main {
public static void main(String[] args){
Thread t1 = new HelloThread("Bob");
t1.start();
Thread t2 = new HelloThread("Alice");
t2.start();
for(int i=0;i<3;i++){
System.out.println("Main!");
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}

3 线程的优先级

  • 可以对线程设定优先级 Thread.setPriority(int n)//1-10,默认值5
  • getPriority()获取线程的优先级
  • 每个线程默认的优先级都与创建它的父线程的优先级相同,默认情况下,main线程具有普通优先级,其子线程也具有普通优先级。
  • 优先级高的线程被操作系统调度的优先级高
  • 不能通过设置优先级来确保功能的执行顺序
public class PriorityTest extends Thread{
public PriorityTest(String name){
super(name);
}
public void run(){
for(int i=0;i<50;i++){
System.out.println(getName()+",其优先级是:"+getPriority()+"的循环变量的值为:"+i);
}
}
public static void main(String[] args){
Thread.currentThread().setPriority(6);
for(int i=0;i<30;i++){
if(i==10){
PriorityTest low = new PriorityTest("低级");
low.start();
System.out.println("创建之初的优先级:"+low.getPriority());
low.setPriority(Thread.MIN_PRIORITY);
}
if(i==20){
PriorityTest high = new PriorityTest("高级");
high.start();
System.out.println("创建之初的优先级:"+high.getPriority());
high.setPriority(Thread.MAX_PRIORITY);
}
}
}
}

高优先级的线程将会获得更多的执行机会,因此尽管高优先级的执行晚,却早结束。



虽然Java提供了10个优先级,但不同操作系统的优先级并不相同,而且也不能很好的和Java的10个优先级对应,因此尽量使用MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY

4总结:

  • Java用Thread对象表示一个线程,通过调用start()启动一个线程
  • 一个线程对象只能调用一次start()
  • 线程的执行代码是run()方法
  • 线程调度由操作系统决定,程序本身无法决定
  • Thread.sleep()可以把当前线程暂停一段时间

廖雪峰Java11多线程编程-1线程的概念-2创建新线程的更多相关文章

  1. 廖雪峰Java11多线程编程-2线程同步-3死锁

    1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...

  2. 廖雪峰Java11多线程编程-1线程的概念-1多线程简介

    多任务 现代操作系统(windows,MacOS,Linux)都可以执行多任务: 多任务就是同时运行多个任务,例如同时开启钉钉.百度网盘.火狐.谷歌.ps等 操作系统执行多任务就是让多个任务交替执行, ...

  3. 廖雪峰Java11多线程编程-4线程工具类-1ThreadLocal

    多线程是Java实现多任务的基础: Thread ExecutorService ScheduledThreadPool Fork/Join Thread对象代表一个线程:调用Tread.curren ...

  4. 廖雪峰Java11多线程编程-2线程同步-4wait和notify

    wait和notify synchronized解决了多线程竞争的问题 我们可以在synchronized块中安全的对一个变量进行修改,但是它没有解决多线程协调的问题. 例如设计一个TaskQueue ...

  5. 廖雪峰Java11多线程编程-1线程的概念-5中断线程

    1.中断线程: 如果线程需要执行一个长时间任务,就可能需要中断线程.场景:从网络上下载一个100M的文件,用户在下载过程中中断下载任务的执行. 中断线程就是其他线程给该线程发一个信号,该线程收到信号后 ...

  6. 廖雪峰Java11多线程编程-1线程的概念-3线程的状态

    1线程的状态 线程终止的的原因: run()或call()方法执行完成,线程正常结束 线程抛出一个未捕获的Exception或Error 直接调用该线程的stop()方法来结束该线程--该方法容易导致 ...

  7. 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

    Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...

  8. 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合

    Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...

  9. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService

    Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...

随机推荐

  1. Excel宏开发之合并单元格

    合并单元格 Sub 宏1() ' ' 宏1 宏 ' ' 快捷键: Ctrl+q ' Application.Goto Reference:="宏1" Application.VBE ...

  2. iOS开发之SceneKit框架--SCNLight.h

    1.SCNLight简介 用于添加光源,连接到一个节点照亮现场,可以给场景添加不同的灯光,模拟逼真的环境. 2.四种灯光的简介 添加一个box立方体.一个tube圆柱管道和一个地板floor,没有灯光 ...

  3. Python入门教程 超详细1小时学会Python

    Python入门教程 超详细1小时学会Python 本文适合有经验的程序员尽快进入Python世界.特别地,如果你掌握Java和Javascript,不用1小时你就可以用Python快速流畅地写有用的 ...

  4. HDU-1698-Just a Hook-区间更新+线段树成段更新

    In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. T ...

  5. HDU-1423-Greatest Common Increasing Subsequence-最长公共上升子序列【模版】

    This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence ...

  6. PAT甲级——A1129 Recommendation System【25】

    Recommendation system predicts the preference that a user would give to an item. Now you are asked t ...

  7. 论文阅读-(CVPR 2017) Kernel Pooling for Convolutional Neural Networks

    在这篇论文中,作者提出了一种更加通用的池化框架,以核函数的形式捕捉特征之间的高阶信息.同时也证明了使用无参数化的紧致清晰特征映射,以指定阶形式逼近核函数,例如高斯核函数.本文提出的核函数池化可以和CN ...

  8. 多边形游戏 /// 区间DP oj1903

    题目大意: ... Input 输入的第一行是单独一个整数n( 3 ≤ n ≤ 18 ),表示多边形的顶点数(同时也是边数). 接下来第n行,每行包含一个运算符("+"或" ...

  9. 16-3-es5解析顺序

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Java开发系列-JSP

    概述 JSP是java 服务器页面,它运行在服务器端,本质上就是一个serlvet,产生的java文件和class保留在tomcat的word目录下. JSP主要作用是将内容的生成与页面相分离. JS ...