
-本文仅是个人学习的总结,便于个人复习. 本文的大部分内容是参考资料中的知识点.

在操作系统级别,程序的执行是基于进程的,通常每个进程中有多个线程可以并行执行而不会互相影响,那么为什么要使用多个线程?实际上,多线程的使用为程序开发带来了极大的便利,特别是以下方面:
1. 使用多线程可以减少程序的响应时间. 在单线程的情况下,如果一个操作很耗时,或者陷入漫长的等待之中. 此时,程序将不响应鼠标和键盘等操作. 使用多线程后,可以将此耗时的线程分配给单独的线程来执行,以使程序具有更好的交互性.
2. 与该过程相比,线程创建和切换开销较小. 由于启动了新线程,因此必须为此线程分配一个独立的地址空间,并且建立了许多数据机制来维护信息,例如线程代码段和数据段,而在统一进程中运行的线程共享代码段,数据段,和线程启动或切换的成本比该过程要少得多. 同时,多线程在数据共享方面非常有效.
3. 多CPU或多核计算机具有执行多线程的能力. 如果使用单个线程,则无法重复使用计算机资源,从而导致资源的巨大浪费. 因此,在多CPU计算机中使用多个线程可以提高CPU利用率.
4. 使用多线程可以简化程序的结构,并且程序易于理解和维护. 一个非常复杂的过程可以分为多个线程来执行.
在多线程环境中,您经常会遇到数据共享问题,即当多个线程需要访问同一资源时,它们需要以某种顺序排列以确保该资源只能由一个线程使用. 一次. 请使用,否则程序的运行结果将不可预测. 在这种情况下,必须同步数据,例如,多个线程同时写入同一数据,也就是说,当线程A需要使用某个资源时,如果线程B正在使用此资源,则同步机制将让线程A等待. 线程A仅在知道线程B使用完资源后才能使用此资源. 这表明同步机制可以确保资源的安全性.
如果要使用同步操作,则每个线程对象必须具有一个锁. 获得它可以保证只有一个线程可以同时进入关键部分(访问互斥资源的代码块),并且在释放锁定之前,其他线程不能进入关键部分. 如果还有其他线程要获取对象的锁,则它们只能进入等待队列并等待. 只有拥有对象锁的线程退出关键部分,并且等待队列中优先级最高的线程才能获取该锁并进入共享代码区域.
Java语言在同步机制中提供语言级别的支持. 您可以使用synced关键字来实现同步,但是这种方法不是“百万美元”,它以较大的系统开销为代价,有时甚至会导致死锁,因此同步控制越多越好,请尝试避免不必要的同步控制. 有两种实现同步的方法: 一种是使用同步代码块实现同步;另一种是使用同步代码块实现同步. 另一种是使用同步方法来实现同步.
异步类似于非阻塞,因为每个线程都包含运行时本身所需的数据或方法,因此在执行输入和输出处理时,您不必关闭其他新线程的状态或行为,也不必关闭等待输入和输出. 处理后退货. 当应用程序在需要很长时间才能执行且不希望程序等待该方法返回的对象上调用方法时,应使用异步编程. 异步编程可以提高程序的效率.
Java虚拟机允许应用程序同时运行多个线程. 在Java语言中,多线程的实现通常具有以下三种方法,其中前两种是最常用的方法.
Thread本质上是Runnable接口的一个实例,它代表一个线程的实例,并且启动线程的唯一方法是通过Thread类的start()
方法. start()方法是本机方法. 它将启动一个新线程并执行run()方法(Thread中提供的run()方法是一个空方法). 这样,您可以直接扩展Thread并覆盖run()方法以启动新线程并执行您定义的run()方法. 应该注意的是,在调用start()方法之后call 多次调用 崩溃 线程安全,多线程代码不会立即执行,而是用于使线程成为Runnable. 何时运行多线程代码由操作系统决定. 例如:
class MyThread extends Thread{//创建线程类
public void run(){
System.out.println("Thread body");
}
}
public class test{
public static void main (String[] args){
MyThread thread = new MyThread();
thread.start();//开启线程
}
}

具体步骤如下:
1. 自定义该类并实现Runnable接口并实现run()方法.
2. 创建一个Thread对象,并使用将Runnable接口实现为参数的对象实例化Thread对象.
3. 调用Thread的start()方法.
class MyThread implements Runnable{//创建线程类
public void run(){
System.out,println("Thread body");
}
}
public class Test{
public static void main(String[] args){
Mythread thread = new MyThread();
thread.start();//开启线程
}
}
Callable接口实际上是Executor框架中的一个功能类. Callable接口类似于Runnable接口,但提供的功能比Runnable更强大. 主要性能如下:
1,Callable可以在任务结束后提供返回值,Runnable无法提供此功能;
2. Callable中的call()方法可以引发异常,而Runnable中的run()方法不能引发异常;
3. 运行Callable可以获得一个Future来监视目标线程对call()方法的调用. 调用Future的get()方法获取结果时,当前线程将阻塞,直到call()方法结束并返回结果为止.
import Java.util.concurrent.*;
public class CallableAndFuture{//创建线程类
public static class CallableTest implements Callable<String>{
public String call() throws Exception{
return "Hello World! ";
}
}
public static void main (String[] args){
ExecutorService threadPool = Executors.newSingleThreadExecutor();
//启动线程
Future<String> future = threadPool.submit(new CallableTest());
try{
System.out.println("waiting thread to finish");
System.out.println(future.get());//等待线程结束,并获取返回结果
}catch (Exception e ){
e,printStackTrace();
}
}
}
以上程序的输出为:
等待线程完成
Hello World!
当需要多线程时,通常建议实现Runnable接口. 原因是: 首先,Tread类定义了派生类可以使用或重写的各种方法. 但是只有run()方法必须重写. 该线程的主要功能是在run()方法中实现的. 其次,许多Java开发人员认为,仅当需要增强或修改类时,才会继承类. 因此,如果不需要重写Thread类中的其他方法,那么继承Thread和Runnable接口的实现的效果类似. 在这种情况下,最好通过实现Runnable接口来创建线程.
通常,系统通过调用线程类的run()方法来启动线程. 此时,线程处于就绪状态,而不是运行状态,这意味着可以调度该线程以供JVM执行. 在调度过程中,JVM通过调用线程类的run()方法来完成实际操作. 当run()方法结束时,线程终止.
![]()
如果直接调用线程类的run()方法,则将其视为常规函数调用. 在程序中,仍然只有主线程,即start()方法可以异步调用run()方法,但是直接调用run()方法是同步的,因此无法实现多线程的目的.
可以看出,只有调用线程类的start()方法才能真正实现多线程的目的. 以下示例说明了run()和start()方法之间的区别:
public void run(){
System.out.println("ThreadDemo:begin");
try{
Thread.sleep(1000);
}catch(InterruptedExceprtion e){
e,printStackTrace():
}
}
public class Test{
public static void test1(){
System.out.println("test1:begin");
Thread t1 = new ThreadDemo();
t1.start();
System.out.println("test1:end");
}
public static void test2(){
System.out.println("test2:begin");
Thread t1 = new ThreadDemo();
t1.run();
System.out.println("test2:end");
}
public static void main(String[] args){
test1();
try{
Thread.sleep(5000);
}catch(InterruptedException e){
//TODO Auto - generated catch block
e.printStackTrace();
}
System.out.println();
test2();
}
}
运行结果为:
test1: 开始
test1: 结束
ThreadDemo: 开始
ThreadDemo: 结束
test2: 开始
ThreadDemo: 开始
ThreadDemo: 结束
test2: 结束
从test1的运行结果可以看出,线程t1是在test1方法结束后执行的,并且可以在不等待t1.start()的运行结果的情况下执行. 异步,因此主线程和t1线程是异步执行的. 从test2的运行结果可以看出,调用t1.run()是同步调用方法.
使用多个线程访问同一资源时,很容易出现线程安全问题(例如,当多个线程同时修改数据时,它将导致某些线程修改数据). 因此,需要一种同步机制来解决这个问题. Java主要提供三种方法来实现同步机制:
在Java语言中,每个对象都有一个与之关联的对象锁. 此锁表示一个对象在任何时候都只能由一个线程拥有. 当线程调用对象的一段同步代码时,需要先获取该锁,然后执行相应的代码,执行结束后,释放该锁.

syncned关键字有两个主要用途(同步方法和同步块). 另外,该关键字还可以应用于静态方法,类或实例,但这对程序的效率有很大的影响.
1,同步方法. 在方法声明之前添加synced关键字,例如:
公共同步的无效mutiThreadAccess();
只要在mutiThreadAccess()方法中需要在资源上同步多个线程,就可以确保该方法一次只能被一个线程访问,从而确保了多线程的安全性访问. 但是,当方法的方法主体大小很大时,将方法声明为已同步将极大地影响程序的执行效率. 为了提高程序效率,Java提供了同步块.
2,同步块. 同步块可以将任何代码段声明为已同步. 您还可以指定具有很高灵活性的锁定对象. 其用法如下:
已同步(syncObject){
//访问syncObject的代码
}
使用同步来装饰共享资源时,如果线程A1正在执行同步代码,并且另一个线程A2还必须执行同一对象的相同同步代码,则线程A2将等待直到线程A1的执行完成后再继续执行. 在这种情况下,可以使用wait()方法和notify()方法.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-182864-1.html
把叙利亚难民危机与光棍危机进行对冲
因为还有中国和这样的国家能制衡美国
美国在反is的问题上本身就是矛盾的