java 一次创建多个线程_廖雪峰Java11多线程编程-1线程的概念-2创建新线程

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

}

}

5edb463c833b1572bab49f050cc17982.png

疯狂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);

}

}

}

edb05539314497fb07943a295c050f37.png

1.2 方法二:使用Runnable接口创建新线程

如果一个类已经从某个类派生,无法从Thread继承:

实现Runnable接口

覆写run()接口

在main()方法中创建Runnable实例

创建Thread实例并传入Runnable

调用start()启动线程

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

}

}

d4ff994d62c95de4a90da3621c6ce857.png

疯狂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);

}

}

}

7cdb994a67155eae3d3cf6d31f677220.png

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

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

class WithResult implements Callable{

@Override

public Integer call() throws Exception {

return 5;

}

}

public class ForZhang {

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

Callable 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 task = new FutureTask((Callable)()->{

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{

@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 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();

}

}

}

27f2712e456cc6b9a396ff0d47fe4819.png

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

}

}

d3359e1c5e65a01499606b3e6b2e9f32.png

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

}

}

}

}

5c613a1597b2f9a2534e4864828f422e.png

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

}

}

}

}

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

8b942d5f9f396fd5f164f4995b931cde.png

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

4总结:

Java用Thread对象表示一个线程,通过调用start()启动一个线程

一个线程对象只能调用一次start()

线程的执行代码是run()方法

线程调度由操作系统决定,程序本身无法决定

Thread.sleep()可以把当前线程暂停一段时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值