获取Map集合中所有的key可以通过map集合的keySet()方法获取例如: Map map = new HashMap(); map.put(xx,xx); //存放数据 //.... 省略 Set set = map.keySet(); //可以通过迭代器进行测试 Iterator iter = set.iter...
public class Point { private int x; private int y; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } ...
一 基本概念
多任务:同一时刻运行多个程序的能力。每一个任务称为一个线程。可以同时运行一个以上线程的程序称为多线程程序。
Java 编写程序都运行在在 Java 虚拟机(JVM)中,在 JVM 的内部,程序的多任务是通过线程来实现的。每用 java 命令启动一个 java 应用程序,就会启动一个 JVM 进程。在同一个 JVM 进程中,有且只有一个进程,就是它自己。在这个 JVM 环境中,所有程序代码的运行都是以线程来运行。
一般常见的 Java 应用程序都是单线程的。比如,用 java 命令运行一个最简单的 HelloWorld 的 Java 应用程序时,就启动了一个 JVM 进程,JVM 找到程序程序的入口点 main(),然后运行 main() 方法,这样就产生了一个线程,这个线程称之为主线程。当 main 方法结束后,主线程运行完成。JVM 进程也随即退出 。
对于一个进程中的多个线程来说,多个线程共享进程的内存块,当有新的线程产生的时候,操作系统不分配新的内存,而是让新线程共享原有的进程块的内存。因此,线程间的通信很容易,速度也很快。不同的进程因为处于不同的内存块,因此进程之间的通信相对困难。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在 Windows 系统中,一个运行的 exe 就是一个进程。
线程是指进程中的一个执行流程,一个进程可以运行多个线程。比如 java.exe 进程可以运行很多线程。线程总是输入某个进程,进程中的多个线程共享进程的内存。
Java 中线程是指 java.lang.Thread 类的一个实例或线程的执行。使用 java.lang.Thread 或 java.lang.Runnable 接口编写代码定义、实例化、启动新线程。
Java 中每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行。main() 方法运行在一个线程内,称为主线程。一旦创建一个新的线程,就产生一个新的调用栈。
线程分为两类:用户线程和守候线程。当所有用户线程执行完毕后,JVM 自动关闭。但是守候线程却不独立与 JVM,守候线程一般是有操作系统或用户自己创建的。
说到多线程,我们不得不先把概念搞清楚,我们通过比较来帮助理解下吧,
(一) 线程和进程的概述
(1) 进程
进程:进程是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源
多线程:在同一个时间段内可以执行多个任务,提高了CPU的使用率
(2) 线程
线程:进程的执行单元,执行路径
单线程:一个应用程序只有一条执行路径
多线程:一个应用程序有多条执行路径
多进程的意义?—— 提高CPU的使用率
多线程的意义? —— 提高应用程序的使用率
(3) 补充
并行和并发
并行是物理上同时发生,指在某一个时间点同时运行多个程序
并发是逻辑上同时发生,指在某一个时间段内同时运行多个程序
Java程序运行原理和JVM的启动是否是多线程的 ?
Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动了一个进程
接着有该进程创建了一个主线程去调用main方法
JVM虚拟机的启动是单线程的还是多线程的 ?
垃圾回收线程也要先启动,否则很容易会出现内存溢出
现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的
JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的
(二) 多线程代码实现
需求:我们要实现多线程的程序。
如何实现呢?
由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。
而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程。
Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序。
但是呢?Java可以去调用C/C++写好的程序来实现多线程程序。
由C/C++去调用系统功能创建进程,然后由Java去调用这样的东西,
然后提供一些类供我们使用。我们就可以实现多线程程序了。
通过查看API,我们知道了有2种方式实现多线程程序。
public class MyThread extends Thread{
public MyThread() { }
@Override
public void run() {
for (int i = 0; i < 100; i++){
System.out.println(getName() + ":" + i);
}
}
}
public class MyThreadTest {
public static void main(String[] args) {
//创建线程对象
MyThread my = new MyThread();
//启动线程,run()相当于普通方法的调用,单线程效果
//my.run();
//首先启动了线程,然后再由jvm调用该线程的run()方法,多线程效果
my.start();
//两个线程演示,多线程效果需要创建多个对象而不是一个对象多次调用start()方法
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
my1.start();
my2.start();
}
}
//运行结果
Thread-1:0
Thread-1:1
Thread-1:2
Thread-0:0
Thread-1:3
Thread-0:1
Thread-0:2
......
Thread-0:95
Thread-0:96
Thread-0:97
Thread-0:98
Thread-0:99
方式2:实现Runnable接口 (推荐)
步骤:
自定义类MyuRunnable实现Runnable接口
重写run()方法
创建MyRunable类的对象
创建Thread类的对象,并把C步骤的对象作为构造参数传递
public class MyRunnable implements Runnable {
public MyRunnable() { }
@Override
public void run() {
for (int i = 0; i < 100; i++){
//由于实现接口的方式不能直接使用Thread类的方法了,但是可以间接的使用
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class MyRunnableTest {
public static void main(String[] args) {
//创建MyRunnable类的对象
MyRunnable my = new MyRunnable();
//创建Thread类的对象,并把C步骤的对象作为构造参数传递
// Thread t1 = new Thread(my);
// Thread t2 = new Thread(my);
//下面具体讲解如何设置线程对象名称
// t1.setName("User1");
// t1.setName("User2");
Thread t1 = new Thread(my,"User1");
Thread t2 = new Thread(my,"User2");
t1.start()
t2.start();
}
}
实现接口方式的好处
可以避免由于Java单继承带来的局限性
适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想
如何理解------可以避免由于Java单继承带来的局限性
比如说,某个类已经有父类了,而这个类想实现多线程,但是这个时候它已经不能直接继承Thread类了
(接口可以多实现implements,但是继承extends只能单继承) ,它的父类也不想继承Thread因为不需要实现多线程
(三) 获取和设置线程对象
//获取线程的名称
public final String getName()
//设置线程的名称
public final void setName(String name)
设置线程的名称 (如果不设置名称的话,默认是Thread-? (编号) )
方法一:无参构造 + setXxx (推荐)
//创建MyRunnable类的对象
MyRunnable my = new MyRunnable();
//创建Thread类的对象,并把C步骤的对象作为构造参数传递
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
t1.setName("User1");
t1.setName("User2");
//与上面代码等价
Thread t1 = new Thread(my,"User1");
Thread t2 = new Thread(my,"User2");
方法二:(稍微麻烦,要手动写MyThread的带参构造方法,方法一不用)
//MyThread类中
public MyThread(String name){
super(name);//直接调用父类的就好
}
//MyThreadTest类中
MyThread my = new MyThread("admin");
获取线程名称
注意:重写run方法内获取线程名称的方式
//Thread
getName()
//Runnable//由于实现接口的方式不能直接使用Thread类的方法了,但是可以间接的使用
Thread.currentThread().getName()
使用实现Runnable接口方法的时候注意:main方法所在的测试类并不继承Thread类,因此并不能直接使用getName()方法来获取名称。
//这种情况Thread类提供了一个方法:
//public static Thread currentThread():
//返回当前正在执行的线程对象,返回值是Thread,而Thread恰巧可以调用getName()方法
System.out.println(Thread.currentThread().getName());
Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的
一 基本概念
多任务:同一时刻运行多个程序的能力。每一个任务称为一个线程。可以同时运行一个以上线程的程序称为多线程程序。
Java 编写程序都运行在在 Java 虚拟机(JVM)中,在 JVM 的内部,程序的多任务是通过线程来实现的。每用 java 命令启动一个 java 应用程序,就会启动一个 JVM 进程。在同一个 JVM 进程中,有且只有一个进程,就是它自己。在这个 JVM 环境中,所有程序代码的运行都是以线程来运行。
一般常见的 Java 应用程序都是单线程的。比如,用 java 命令运行一个最简单的 HelloWorld 的 Java 应用程序时,就启动了一个 JVM 进程,JVM 找到程序程序的入口点 main(),然后运行 main() 方法,这样就产生了一个线程,这个线程称之为主线程。当 main 方法结束后,主线程运行完成。JVM 进程也随即退出 。
对于一个进程中的多个线程来说,多个线程共享进程的内存块,当有新的线程产生的时候,操作系统不分配新的内存,而是让新线程共享原有的进程块的内存。因此,线程间的通信很容易,速度也很快。不同的进程因为处于不同的内存块,因此进程之间的通信相对困难。
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在 Windows 系统中,一个运行的 exe 就是一个进程。
线程是指进程中的一个执行流程,一个进程可以运行多个线程。比如 java.exe 进程可以运行很多线程。线程总是输入某个进程,进程中的多个线程共享进程的内存。
Java 中线程是指 java.lang.Thread 类的一个实例或线程的执行。使用 java.lang.Thread 或 java.lang.Runnable 接口编写代码定义、实例化、启动新线程。
Java 中每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行。main() 方法运行在一个线程内,称为主线程。一旦创建一个新的线程,就产生一个新的调用栈。
线程分为两类:用户线程和守候线程。当所有用户线程执行完毕后,JVM 自动关闭。但是守候线程却不独立与 JVM,守候线程一般是有操作系统或用户自己创建的。
2018-04-11 回答
先理解这几概念:a1.程序:指令和数据的byte序列,eg:qq.exe;a2.进程:正在运行的程序(如QQ);a3.一个进程中可能有一到多个线程.
线程的概念:Thread 每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。
线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。
所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。
多线程的概念: 多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。
线程是在同一时间需要完成多项任务的时候实现的。
多线程的优点:使用线程可以把占据长时间的程序中的任务放到后台去处理
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度 ·
程序的运行速度可能加快 ·在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。
在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
1、继承Thread类实现多线程
继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。
在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。利用线程,用户可按下一个按钮,然后程序会立即作出响应,而不是让用户等待程序完成了当前任务以后才开始响应。简单地说,就是说可以有多个任务同时进行。单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。因此,针对前面举的例子,必须等待程序完成了当前任务以后才能开始相应。 使用多线程访问公共的资源时,容易引发线程安全性问题,因此针对这种需要使用线程同步机制来保护公共的资源。单线程较多线程来说,就不会出现上诉问题,系统稳定、扩展性极强、软件丰富。多用于点对点的服务。
Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
相关问题推荐
对于每一位才开始接触JAVA的新手来说,先不要管算法和数据结构,大多数简单的程序不需要用到算法和数据结构,所以当你真正需要时再去学习。编程一段时间以后,你就会知道在哪些地方用到他们。这时知道算法的名字并了解它们的功能,然后动手去实践。当我们在去...
2个都很好就业,更关键的是要学得到东西
获取Map集合中所有的key可以通过map集合的keySet()方法获取例如: Map map = new HashMap(); map.put(xx,xx); //存放数据 //.... 省略 Set set = map.keySet(); //可以通过迭代器进行测试 Iterator iter = set.iter...
不同年龄,不同掌握程度,学历,找工作城市,面试能力这是一个多方面影响的结果,如果是平均值的话,全国平均薪资14k左右
具体学多久,根据自己的学习力,自律性、解决问题能力来决定若系统性学习,跟着讲师的节奏走,大概半年左右,有专业的讲师把课程进行规划,尽心系统学习,有问题,讲师会帮忙解决,学习的效率很高,避免了自学中出现各种问题解决不了,而耽误很多时间,可能会...
(1)idea启动时会有两个快捷方式,安装完后默认生成在桌面的是32位的idea的快捷方式,如果我们使用这个快捷方式运行大项目,一般都会很卡。解决方法是找到idea的安装目录,然后进入bin文件夹,找到名称为idea64的应用程序,右键他生成桌面快捷方式。以后每次...
IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。一、BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要...
ava是一种区分字母的大小写的语言,所以我们在定义变量名的时候应该注意区分大小写的使用和一些规范,接下来我们简单的来讲讲Java语言中包、类、变量等的命名规范。(一)Package(包)的命名Package的名字应该都是由一个小写单词组成,例如com、xuetang9、compan...
public class Point { private int x; private int y; public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } ...
经典版单例模式public class Singleton { private static Singleton uniqueInstance;//利用一个静态常量来记录singleton类的唯一实例。 private Singleton() { } public static Singleton getInstance()...
哈希表的长度一般是定长的,在存储数据之前我们应该知道我们存储的数据规模是多大,应该尽可能地避免频繁地让哈希表扩容。但是如果设计的太大,那么就会浪费空间,因为我们跟不用不到那么大的空间来存储我们当前的数据规模;如果设计的太小,那么就会很容易发...
1. DOM(Document Object Model) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才...
1)作用不同: throw用于程序员自行产生并抛出异常; throws用于声明在该方法内抛出了异常2) 使用的位置不同: throw位于方法体内部,可以作为单独语句使用; throws必须跟在方法参数列表的后面,不能单独使用。3)内容不同: throw抛出一个异常对象,且只能是...
基本执行过程如下:1)程序首先执行可能发生异常的try语句块。2)如果try语句没有出现异常则执行完后跳至finally语句块执行;3)如果try语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch语句块执行处理。4)catch语句块可以有多个,分别捕获不同类型...
100-199 用于指定客户端应相应的某些动作。 200-299 用于表示请求成功。 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。 400-499 用于指出客户端的错误。 400 语义有误,当前请求无法被服务器理解。 401 当前请求需要用户验证...
异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译...