java 调用 dll是多线程的_浅谈多线程_让程序更高效的运行

本文深入探讨Java中的多线程概念,包括线程与进程的区别、同步异步、阻塞非阻塞、临界资源与线程安全。通过示例解析线程的创建、生命周期以及守护线程、中断机制。同时,文章还介绍了wait和notify在同步控制中的作用,帮助读者理解Java线程管理的精髓。
摘要由CSDN通过智能技术生成

Java Thread 的一些认识:

Java是抢占式线程,一个线程就是进程中单一的顺序控制流,单个进程可以拥有多个并发任务,其底层是切分CPU时间,多线程和多任务往往是使用多处理器系统的最合理方式

进程可以看作一个程序或者一个应用;线程是进程中执行的一个任务,多个线程可以共享资源

一个Java 应用从main 方法开始运行,main 运行在一个线程内,也被称为 “主线程”,Runnable也可以理解为Task (任务)

JVM启动后,会创建一些守护线程来进行自身的常规管理(垃圾回收,终结处理),以及一个运行main函数的主线程

随着硬件水平的提高,多线程能使系统的运行效率得到大幅度的提高,同时异步操作也增加复杂度和各种并发问题

0dfa70fe78a5756f183a2ee8f0350e32.png

■ 线程 VS 进程

在一个已有进程中创建一个新线程比创建一个新进程快的多

终止一个线程比终止一个进程快的多

同一个进程内线程间切换比进程间切换更快

线程提供了不同的执行程序间通信的效率,同一个进程中的线程共享同一进程内存和文件,无序调用内核就可以互相通信,而进程间通信必须通过内核

■ 同步和异步

同步方法一旦开始,调用者必须等到方法调用返回之后,才能继续后续行为

无先后顺序,一旦开始,方法调用便立即返回,调用者就可以继续后续行为,一般为另一个线程执行

■ 阻塞和非阻塞

当一个线程占用临界区资源,其他线程也想要使用该资源就必须等待,等待会导致线程的挂起,也就是阻塞(线程变成阻塞状态)。

此时若占用资源的线程一直不愿意释放资源,那么其他所有阻塞在该临界区的线程都会被挂起,变成阻塞状态,不能正常工作,直到占用线程释放资源

非阻塞强调没有一个线程可以妨碍其他线程执行,所有线程都会尝试去做下一步工作

■ 临界资源与临界区

一般指的是公共共享资源,即可以被多个线程共享使用。但同一时间只能由一个线程去访问和操作临界区的资源,一旦临界区资源被一个线程占用,其他线程也想要使用该资源就必须等待,

就好比好多人想上大号,但只有一个坑,一个人占了坑,其他人就得排队等待喽

临界区可以认为是一段代码,线程会在该端代码中访问共享资源,因此临界区的界定标准就是是否访问共享(临界)资源(有点类似形成闭包的概念);一次只允许有一个程序(进程/线程)在该临界区中

■ 类定义

public class Thread implements Runnable {

/* Make sure registerNatives is the first thing does.

初始化时调用 Java 本地方法,实现了Runnable接口

*/

private static native void registerNatives();

static {

registerNatives();

}

■ 构造器

/**

* 默认构造器

* 其中name规则为 "Thread-" + nextThreadNum()

*/

public Thread() {

init(null, null, "Thread-" + nextThreadNum(), 0);

}

/**

* 创建一个指定Runnable的线程

* 其中name规则为 "Thread-" + nextThreadNum()

*/

public Thread(Runnable target) {

init(null, target, "Thread-" + nextThreadNum(), 0);

}

/**

* 创建一个指定所属线程组和Runnable的线程

* 其中name规则为 "Thread-" + nextThreadNum()

*/

public Thread(ThreadGroup group, Runnable target) {

init(group, target, "Thread-" + nextThreadNum(), 0);

}

/**

* 创建一个指定name线程

*/

public Thread(String name) {

init(null, null, name, 0);

}

/**

* 创建一个指定所属线程组和name的线程

*/

public Thread(ThreadGroup group, String name) {

init(group, null, name, 0);

}

/**

* 创建一个指定Runnable和name的线程

*/

public Thread(Runnable target, String name) {

init(null, target, name, 0);

}

/**

* Allocates a new {@code Thread} object so that it has {@code target}

* as its run object, has the specified {@code name} as its name,

* and belongs to the thread group referred to by {@code group}.

* 创建一个新的Thread对象,同时满足以下条件:

* 1.该线程拥有一个指定的Runnable对象用于方法执行

* 2.该线程具有一个指定的名称

* 3.该线程属于一个指定的线程组ThreadGroup

*

If there is a security manager, its

* {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}

* method is invoked with the ThreadGroup as its argument.

* 若这里有个安全管理器,则ThreadGroup将调用checkAccess方法进而触发SecurityManager的checkAccess方法

*

In addition, its {@code checkPermission} method is invoked with

* the {@code RuntimePermission("enableContextClassLoaderOverride")}

* permission when invoked directly or indirectly by the constructor of a subclass which

* overrides the {@code getContextClassLoader} or {@code setContextClassLoader} methods.

* 当enableContextClassLoaderOverride被开启时,checkPermission将被重写子类直接或间接地调用

*

The priority of the newly created thread is set equal to the

* priority of the thread creating it, that is, the currently running

* thread. The method {@linkplain #setPriority setPriority} may be

* used to change the priority to a new value.

* 新创建的Thread的优先级等同于创建它的线程的优先级,调用setPriority会变更其优先级

*

The newly created thread is initially marked as being a daemon

* thread if and only if the thread creating it is currently marked

* as a daemon thread. The method {@linkplain #setDaemon setDaemon}

* may be used to change whether or not a thread is a daemon.

* 当且仅当线程创建时被显示地标记为守护线程,新创建的线程才会被初始化为一个守护线程

* setDaemon方法可以设置当前线程是否为守护线程

*/

public Thread(ThreadGroup group, Runnable target, String name) {

init(group, target, name, 0);

}

/**

* Allocates a new {@code Thread} object so that it has {@code target} as its run object,

* has the specified {@code name} as its name, and belongs to the thread group referred to

* by {@code group}, and has the specified stack size.

* 创建一个新的Thread对象,同时满足以下条件:

* 1.该线程拥有一个指定的Runnable对象用于方法执行

* 2.该线程具有一个指定的名称

* 3.该线程属于一个指定的线程组ThreadGroup

* 4.该线程拥有一个指定的栈容量

*

This constructor is identical to {@link #Thread(ThreadGroup,Runnable,String)}

* with the exception of the fact that it allows the thread stack size to be specified.

* The stack size is the approximate number of bytes of address space that the virtual machine

* is to allocate for this thread's stack. The effect of the {@code stackSize} parameter,

* if any, is highly platform dependent.

* 栈容量指的是JVM分配给该线程的栈的地址(内存)空间大小,这个参数的效果高度依赖于JVM运行平台

*

On some platforms, specifying a higher value for the {@code stackSize} parameter may allow

* a thread to achieve greater recursion depth before throwing a {@link StackOverflowError}.

* Similar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java多线程可以调用DLL(Dynamic-Link Library)来进行一些特定操作。 首先,在Java调用DLL需要使用到Java Native Interface(JNI)技术。JNI是Java提供的一种机制,用于在Java程序调用本地的C/C++代码。通过JNI,我们可以在Java程序中加载和调用DLL中的函数。 在多线程调用DLL的过程如下: 1. 首先,在Java中编写一个JNI的接口类,用于定义与DLL中函数的映射关系。这个接口类需要使用Java的native关键字来声明与DLL中函数对应的本地方法。 2. 在DLL中实现与接口类中声明的本地方法对应的C/C++函数。这些函数可以通过DLL导出符号的方式供Java程序调用。 3. 在Java程序中加载DLL调用其中的函数。 使用多线程调用DLL时,需要注意以下几点: 1. 线程安全性:在多线程环境下调用DLL时,需要确保DLL中的函数是线程安全的,即能够正确处理多个线程间的共享数据。 2. 同步控制:如果DLL中的函数需要访问共享资源,需要在Java程序中使用同步控制机制,如synchronized关键字或Lock对象来确保线程之间的互斥访问。 3. 线程间通信:如果多个线程需要相互通信,可以通过共享内存或消息传递的方式实现。在DLL中可以使用线程同步的机制来实现线程间的互斥、等待和通知操作。 总之,Java多线程可以通过JNI技术调用DLL来完成一些底层的特定操作。在进行多线程调用DLL时,需要保证线程安全性,确保合适的同步控制和线程间通信方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值