java执行程序默认多线程吗_Java多线程 执行程序(1)

本文由作者收集整理所得,作者不保证内容的正确行,转载请标明出处。

作者:关新全

Java多线程

执行程序(1)

1.1

Thread类

static Thread.currentThread

返回当前正在执行的线程对象的引用。

join 等待线程终止。

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

Demo1-1中给出的程序中,主函数中创建了两个线程,每个子线程第一条输出语句执行结束后,放弃了执行权,从而让其他线程有机会继续执行。这样就会看到子线程1和子线程2交叉输出的信息。在主线程中使用了join方法,阻塞等待子线程执行结束,当两个子线程将其内部的信息全部输出后,主线程才将其线程线性输出。(Thread.currentThread的输出格式为,[子线程名,线程优先级,线程组名])。最后,在main函数内部需要调用内部类,内部类应当为static。一般情况下,内部类和内部接口都应当是static的。

Demo 1-1 Thread

类的用法

package com.upc.upcgrid.guan.advancedJava.chapter02;

public class YieldTest {

public static class ThreadImpl implements Runnable{

@Override

public void run() {

System.err.println(Thread.currentThread());

Thread.yield();

System.err.println(Thread.currentThread());

}

}

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

Thread t1 = new Thread(new ThreadImpl());

Thread t2 = new Thread(new ThreadImpl());

t1.start();

t2.start();

t1.join();

t2.join();

System.err.println(Thread.currentThread());

}

}

Demo1-1 输出结果

Thread[Thread-0,5,main]

Thread[Thread-1,5,main]

Thread[Thread-0,5,main]

Thread[Thread-1,5,main]

Thread[main,5,main]

1.2 Executor

接口

Executor可以定制创建特殊的子线程。例如,在创建一系列的子线程时,对子线程进行同样的配置,如果,需要修改或增强子线程的开启或配置,只需修改Executor的实现即可。

在Demo1-2中,主线程通过Executor接口创建和执行一个新的线程。在Executor接口的ExecutorInterface实现中,可以对所有的线程进行一些默认的配置,然后启动执行这个线程。如果,此时我们需要修改这个系列线程的优先级,只需要修改ExecutorInterface接口中的相应值即可,无需修改代码中的所有创建线程的地方。(有时可以在Executor的executor的方法实现中使用一定的线程调度策略,这样可以为线程调度提供灵活性,当修改线程调度的实现时,不影响外部使用的代码)。

Demo1-3实现了一个线程优先队列的Executor,在这样的Executor中,每次提交的任务会被放入一个队列中,Executor最多只开启一个线程执行这个队列中的任务,而且队列使用优先级策略,就是优先级高的线程将会先被Executor执行,优先级低的线程将需等待优先级高的线程执行结束后,才能获得执行权。从代码中看出,创建了5个线程,设置了不同的优先级,并提交个Executor去执行。从执行结果可以看出,线程基本是按照线程优先级次序执行的(线程优先级5先执行,因为在他提交的时候队列中并没有其他线程,他的优先级最高,因此它被最先执行了,也就是说这个优先级还与线程的提交次序有关)。Executor更倾向于开启一个线程,在稍后对ExecutorFactory介绍时,可以看出,他们一个是执行线程,一个是创建线程。

Demo 1-2

Executor接口的使用

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.lang.Thread.UncaughtExceptionHandler;

import java.util.concurrent.Executor;

public class ExecutorInterface implements Executor{

@Override

public void execute(Runnable command) {

Thread t = new Thread(command);

t.setDaemon(false);

t.setPriority(6);

t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {

@Override

public void uncaughtException(Thread t, Throwable e)

{

System.err.println(e.getMessage());

}

});

t.start();

}

private static class RunnableImpl implements Runnable{

@Override

public void run() {

System.err.println(Thread.currentThread());

}

}

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

ExecutorInterface e = new ExecutorInterface();

e.execute(new RunnableImpl());

e.execute(new RunnableImpl());

}

}

Demo1-3 线程池的初探

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.Executor;

import java.util.concurrent.PriorityBlockingQueue;

public class ExecutorInterfaceWithSchedule

implements Executor{

private BlockingQueue

queue = new PriorityBlockingQueue();

private Thread t;

public ExecutorInterfaceWithSchedule() {

Thread inner =new Thread(new Runnable() {

@Override

public void run() {

try {

while(true)

{

t = new Thread(queue.take());

t.start();

t.join();//等待线程结束

}

} catch (InterruptedException e) {

}

}

});

inner.setDaemon(true);

inner.start();

}

@Override

public void execute(Runnable command) {

try {

queue.put(command);

} catch (InterruptedException e) {

}

}

private static class ThreadImpl implements Runnable,Comparable{

public int priority;

public ThreadImpl(int priority) {

this.priority = priority;

}

@Override

public void run() {

System.err.println(Thread.currentThread() +

String.valueOf(priority));

}

@Override

public int compareTo(ThreadImpl o) {

return o.priority > priority?1:0;

}

}

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

ThreadImpl t1 = new ThreadImpl(5);

ThreadImpl t2 = new ThreadImpl(6);

ThreadImpl t3 = new ThreadImpl(7);

ThreadImpl t4 = new ThreadImpl(1);

ThreadImpl t5 = new ThreadImpl(4);

ExecutorInterfaceWithSchedule executor = new ExecutorInterfaceWithSchedule();

executor.execute(t1);

executor.execute(t2);

executor.execute(t3);

executor.execute(t4);

executor.execute(t5);

Thread.sleep(10000);

}

}

Demo1-3执行结果:

Thread[Thread-1,5,main]5

Thread[Thread-2,5,main]7

Thread[Thread-3,5,main]6

Thread[Thread-4,5,main]4

Thread[Thread-5,5,main]1

Graphic 1-1

与Executor有关的接口

a4c26d1e5885305701be709a3d33442f.png

1.3

ExecutorService接口

ExecutorService接口用于管理Executor接口,用于跟踪一个和多个异步任务的执行。简单的说就是提供一个线程池的功能,可以向线程池中提交多个任务,线程池根据具体的实现,采用一定的调度方法和策略对提交的线程进行排队和执行。

ExecutorService提供了shutDown方法,可以终止线程池继续接受新的任务,使用shutDown方法并不会立即取消正在执行的任务,他会在线程任务执行结束后,自动关闭并释放线程资源。shutDownNow方法则不同,线程池会尝试试图关闭正在执行的线程。

Submit扩展了Executor接口的executor方法,并返回一个Future,用来取消或查询线程任务。invokeAll和invokeAny方法是批量执行任务的常见形式。invokeAll是等待所有任务结束才返回,而invokeAny是其中有一个任务完成就返回。

一般通过Executors类的静态函数来创建相应的ExecutorService实例。

Demo 1-4中,主线程先创建了十个任务,然后将这十个任务的集合提交给线程池执行,线程池的大小是3,线程池根据内部的调度策略去调度执行任务,从最终的输出可以看出,线程池的子线程1执行的任务最多。最终在主线程中进行结果统计,关闭线程池。需要注意的是,线程池的关闭需要手动代码,而且还要给出出错的情况下如何合理的终结线程池。

Demo 1-4 线程池的使用:

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;

public class ExecuteServiceInterface {

public static final int THREAD_SIZE = 10;

private static class onceCompute implements Callable{

private int start;

private int end;

public onceCompute(int start,int end) {

this.start = start;

this.end = end;

}

@Override

public Integer call() throws Exception {

int sum = 0;

for(int i = start ; i < end ; i++)

{

sum += i;

}

System.err.println(Thread.currentThread());

return sum;

}

}

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

{

ExecutorService pool =

Executors.newFixedThreadPool(3);//创建3个线程的线程池

List>

calls = new ArrayList>();//任务集合

for(int i = 0 ; i < THREAD_SIZE ;i++)//创建任务

{

calls.add(new onceCompute(i*100, (i+1)*100));

}

List>

futures = pool.invokeAll(calls);//阻塞等待任务完成

int sum = 0;

for(Future f :

futures)//汇总任务计算结果

{

sum +=f.get();

}

System.out.println(sum);//输出结果

//线程池的关闭策略

pool.shutdown();

try {

pool.awaitTermination(1000, TimeUnit.MILLISECONDS);

} catch (InterruptedException e) {

pool.shutdownNow();

Thread.currentThread().interrupt();

}

}

}

Demo 1-4 的执行结果:

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-3,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-1,5,main]

Thread[pool-1-thread-2,5,main]

Thread[pool-1-thread-3,5,main]

499500

1.4

ScheduleExecutorService

从Graphic1-1可以看出ScheduleExecutorService是继承于ExecutorService的一个增强的接口。这个接口在ExecutorService接口的基础上增加了四个操作,可以分为三种类型,一种类型是schedule函数,用于在指定延时后创建一个线程执行某项任务,一种是scheduleAtFixedRate在指定延时后,创建一个周期性执行的线程任务,还有一种是scheduleWithFixedDelay,在指定延时后以一定的延时执行线程任务。第二和第三种的区别在于,第二种计算的是周期,这个时间间隔是指定好的。第三种是延时,是指从一次执行结束,到下一次执行开始的这段时间,这种方式将线程执行的时间也考虑在内。

Demo 1-5 给出了这个示例,每个1s中输出当前时间。

Demo1-5 定期任务

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduleExecutorServiceInterface {

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

ScheduledExecutorServicepool =

Executors.newSingleThreadScheduledExecutor();

pool.scheduleAtFixedRate(new Runnable() {

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

@Override

public void run() {

System.err.println(df.format(new Date()));

}

}, 1000,1000,TimeUnit.MILLISECONDS);

Thread.sleep(10000);

pool.shutdownNow();

}

}

1.5

ThreadFactory接口

这个接口用于创建一个新的线程,它与Executor接口的区别在于,Executor接口更强调的是执行和管理一个线程,而ThreadFactory强调的是如何创建一个线程。在很多的Executor实现中,需要提供一个ThreadFactory实例,毕竟Executor类中使用new方法创建一个线程是不合理的,因为如果用户对新线程的配置进行更改,这种更改将会被延伸到Executor接口的所有实现子类,这不利于代码的扩展。ThreadFactory仅有一个方法newThread,实现这个方法,用于创建自己的线程逻辑。

Demo1-6中,ThreadFactory用来指定创建多线程的方式,定制多线程的创建方法,而Executor则更强调如何执行,如何管理多线程。所以,在Executor类中应当有一个ThreadFactory引用,这样在Executor类中就无需显示使用new,并且负责与线程相关的配置,当需要对线程的属性进行配置时,不会影响到Executor的内部实现。

ThreadFactory主要使用的是设计模式中的工厂方法模式,可以参考设计模式的相应章节。

Demo1-6

ThreadFactory与Executor的关系

package com.upc.upcgrid.guan.SpecialUse.chapter01;

import java.util.concurrent.Executor;

import java.util.concurrent.ThreadFactory;

public class ThreadFactoryInterface {

private static class ExecutorImp implements Executor{

private static ThreadFactory threadFactory;

@SuppressWarnings("unused")

public ExecutorImp() {

threadFactory = new ThreadFactory() {

@Override

public Thread newThread(Runnable r) {

return new Thread(r);

}

};

}

@SuppressWarnings("static-access")

public ExecutorImp(ThreadFactory tf){

this.threadFactory = tf;

}

@Override

public void execute(Runnable command) {

Thread t = threadFactory.newThread(command);

t.start();

}

}

private static class ThreadFacotoryImp implements ThreadFactory{

@Override

public Thread newThread(Runnable r) {

Thread t = new Thread(r);

t.setDaemon(false);

t.setPriority(7);

return t;

}

}

public static void main(String[] args) {

Executor executor = new ExecutorImp(new ThreadFacotoryImp());

executor.execute(new Runnable() {

@Override

public void run() {

System.out.println(Thread.currentThread());

}

});

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/475184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 531. 孤独像素 I

文章目录1. 题目2. 解题1. 题目 给定一幅黑白像素组成的图像, 计算黑色孤独像素的数量。 图像由一个由‘B’和‘W’组成二维字符数组表示, ‘B’和‘W’分别代表黑色像素和白色像素。 黑色孤独像素指的是在同一行和同一列不存在其他黑色像素的黑色像素。 示例: 输入: [[W,…

LeetCode 533. 孤独像素 II

文章目录1. 题目2. 解题1. 题目 给定一幅由黑色像素和白色像素组成的图像&#xff0c; 与一个正整数N, 找到位于某行 R 和某列 C 中且符合下列规则的黑色像素的数量: 行R 和列C都恰好包括N个黑色像素。列C中所有黑色像素所在的行必须和行R完全相同。 图像由一个由‘B’和‘W…

Windows 8桌面的尴尬

刚出炉的Windows8可谓荣宠极致&#xff0c;此时却被指出存在问题&#xff0c;面临失宠的尴尬。到底是什么问题呢&#xff1f; Windows 8中新的用户界面&#xff0c;已被完全证明是两级分化日益严重。  混合操作系统是一个新的GUI概念&#xff0c;友好地触摸界面接口&#xff…

LeetCode 1101. 彼此熟识的最早时间(排序+并查集)

文章目录1. 题目2. 解题1. 题目 在一个社交圈子当中&#xff0c;有 N 个人。每个人都有一个从 0 到 N-1 唯一的 id 编号。 我们有一份日志列表 logs&#xff0c;其中每条记录都包含一个非负整数的时间戳&#xff0c;以及分属两个人的不同 id&#xff0c;logs[i] [timestamp,…

【转载】世界各地对BI的应用状况

欧美企业对商务智能的应用 商务智能活动在美国和欧洲比在世界上任何其他地区都要发达&#xff0c;商务智能已经由“旁门左道”转变为“主门正道”。欧美的企业已经认识到商务智能的重要意义&#xff0c;因而对它寄予很高的期望&#xff0c;希望能够通过商务智能充分利用企业以往…

php gearman 扩展,Ubuntu 12.04 安装 gearman 以及php扩展安装脚本

#!/usr/bash#create by lhb#date 2014-05-07#desc install gearman and php extension for Ubuntu 12.04.4 LTS PHP 5.5apt-get update#安装依赖库apt-get install libboost-all-dev gperf libevent1-dev libcloog-ppl0mkdir -pv /home/lhb/software && cd /home/lhb/s…

LeetCode 379. 电话目录管理系统(哈希set)

文章目录1. 题目2. 解题1. 题目 设计一个电话目录管理系统&#xff0c;让它支持以下功能&#xff1a; get: 分配给用户一个未被使用的电话号码&#xff0c;获取失败请返回 -1check: 检查指定的电话号码是否被使用release: 释放掉一个电话号码&#xff0c;使其能够重新被分配 …

LeetCode 250. 统计同值子树(递归)

文章目录1. 题目2. 解题1. 题目 给定一个二叉树&#xff0c;统计该二叉树数值相同的子树个数。 同值子树是指该子树的所有节点都拥有相同的数值。 示例&#xff1a; 输入: root [5,1,5,5,5,null,5]5/ \1 5/ \ \5 5 5 输出: 4来源&#xff1a;力扣&#xff08;LeetC…

php 函数报错,PHP报错函数error_reporting()怎么用?

PHP中&#xff0c;报错函数error_reporting()用于规定应该报告何种PHP错误&#xff0c;语法“error_reporting(level)”&#xff1b;使用该函数可以设置在脚本运行时的错误级别&#xff0c;如果没有设置可选参数level&#xff0c;则仅返回当前的错误报告级别。推荐&#xff1a;…

LeetCode 426. 将二叉搜索树转化为排序的双向链表(BST中序循环遍历)

文章目录1. 题目2. 解题1. 题目 将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。 对于双向循环列表&#xff0c;你可以将左右孩子指针作为双向循环链表的前驱和后继指针&#xff0c;第一个节点的前驱是最后一个节点&#xff0c;最后一个节点的后继是第一个节点。 …

LeetCode 285. 二叉搜索树中的顺序后继(中序遍历)

文章目录1. 题目2. 解题1. 题目 给你一个二叉搜索树和其中的某一个结点&#xff0c;请你找出该结点在树中顺序后继的节点。 结点 p 的后继是值比 p.val 大的结点中键值最小的结点。 示例 1: 输入: root [2,1,3], p 1 输出: 2 解析: 这里 1 的顺序后继是 2。 请注意 p 和…

LeetCode 510. 二叉搜索树中的中序后继 II(查找右子树或者祖父节点)

文章目录1. 题目2. 解题1. 题目 给定一棵二叉搜索树和其中的一个节点 node &#xff0c;找到该节点在树中的中序后继。 如果节点没有中序后继&#xff0c;请返回 null 。 一个结点 node 的中序后继是键值比 node.val大所有的结点中键值最小的那个。 你可以直接访问结点&…

一个关于Remoting的简单例子

前言 今天在整理以前写的一些demo&#xff0c;看到一个关于remoting的例子。好久不用remoting了&#xff0c;果断记录一下。 什么是Remoting 简单回顾下&#xff1a; 1.Remoting是一种远程通信&#xff0c;或者说跨应用程序&#xff08;域&#xff09;通信的技术,在C/S架构的程…

php mqtt qos,Mqtt Qos 深度解读

1.QoS含义 &#xff1a;Quality of Service,服务质量2.作用域发布者的Qos订阅者的Qos3.等级与作用level 0&#xff1a;最多一次的传输level 1&#xff1a;至少一次的传输&#xff0c;(鸡肋)level 2&#xff1a; 只有一次的传输4.交互过程qos0对于qos1而言&#xff0c;对于clien…

LeetCode 1502. 判断能否形成等差数列

文章目录1. 题目2. 解题1. 题目 给你一个数字数组 arr 。 如果一个数列中&#xff0c;任意相邻两项的差总等于同一个常数&#xff0c;那么这个数列就称为 等差数列 。 如果可以重新排列数组形成等差数列&#xff0c;请返回 true &#xff1b;否则&#xff0c;返回 false 。 …

matlab2017调用vgg19,VGG19模型训练+读取

VGG-19的介绍和训练这里不做说明,网上资源很多,而且相对比较简单.本博文主要介绍VGG-19模型调用官方已经训练好的模型,进行测试使用.[TOC]VGG-19模型简单介绍VGG模型使用VGG结构模型VGG具体参数模型VGG-19模型文件介绍这里是重难点,VGG-19模型存储的方式有点复杂可以通过作者文…

LeetCode 1504. 统计全 1 子矩形(记录左侧的连续1的个数)

文章目录1. 题目2. 解题1. 题目 给你一个只包含 0 和 1 的 rows * columns 矩阵 mat &#xff0c; 请你返回有多少个 子矩形 的元素全部都是 1 。 示例 1&#xff1a; 输入&#xff1a;mat [[1,0,1],[1,1,0],[1,1,0]] 输出&#xff1a;13 解释&#xff1a; 有 6 个 1x1 的矩…

matlab中ode23s使用方法,MATLAB中ode23函数,龙格库塔函数

今天说一说MATLAB中ode23函数的原理&#xff0c;在网上看了好多&#xff0c;但是不知道是怎么计算的&#xff0c;就知道是那么用的&#xff0c;但是最后结果咋回事不知道&#xff0c;今天来讲一讲是怎么计算的。首先来个程序&#xff1a;function feg6fun(t,y)f-y^3-2;end上面是…

LeetCode 1503. 所有蚂蚁掉下来前的最后一刻(脑筋急转弯)

文章目录1. 题目2. 解题1. 题目 有一块木板&#xff0c;长度为 n 个 单位 。一些蚂蚁在木板上移动&#xff0c;每只蚂蚁都以 每秒一个单位 的速度移动。其中&#xff0c;一部分蚂蚁向 左 移动&#xff0c;其他蚂蚁向 右 移动。 当两只向 不同 方向移动的蚂蚁在某个点相遇时&a…

LeetCode 1246. 删除回文子数组(区间DP)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 arr&#xff0c;每一次操作你都可以选择并删除它的一个 回文 子数组 arr[i], arr[i1], ..., arr[j]&#xff08; i < j&#xff09;。 注意&#xff0c;每当你删除掉一个子数组&#xff0c;右侧元素都会自行向前移动填补空…