Java学习笔记44(多线程一:Thread类)
多线程的概念:略
多线程的目的:提高效率
主线程:
package demo;
//主线程
public class Demo {
public static void main(String[] args) {
function();
System.out.println(1);
} public static void function(){
for (int i = 0; i < 10000; i++) {
System.out.println(i);
}
}
}
这段简单的代码,我们发现:
必须要先执行方法输出完10000次的数字后才可以打印第二行的数字1
那么有没有方法,可以做到在执行方法的同时执行第二行的输出?
Thread类
创建新线程的两种方法:
第一种:
package demo;
public class SubThread extends Thread {
//重写run方法
public void run(){
for(int i = 0 ; i< 50 ; i++){
System.out.println(i+"run");
}
}
}
package demo;
public class ThreadDemo {
public static void main(String[] args) {
SubThread st1 = new SubThread();
st1.start();
for (int i = 0; i < 50; i++) {
System.out.println(i+"main");
}
}
}
这里输出时候,发现打印的run和main随机出现,交错出现,而不像以前那样按顺序打印
原因:创建了新的线程,两条线程由cpu选择执行,我们无法控制
start方法开启新的线程,继承了Thread类因为只有继承了它才可以操作线程
重写run方法因为,Thread类本身没有写入有意义的run方法,相当于一个模板,供开发者使用
线程名:
每个线程都有自己的名字,主线程名:main,其他新建线程默认名:Thread-n
获取、修改线程名:
package demo1;
public class NameThread extends Thread {
public void run(){
System.out.println(super.getName());
//输出:默认是Thread-0,如果修改了,就是hello
}
}
package demo1;
public class ThreadDemo {
public static void main(String[] args) {
NameThread nt1 = new NameThread();
nt1.setName("hello");
//修改线程名为hello,主线程不能改名
nt1.start();
Thread t = Thread.currentThread();
System.out.println(t.getName());
//输出:main
}
}
Thread类的一个实用方法:
package demo1;
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println(i);
}
//每次打印都会等待一秒,参数是毫秒值
}
}
第二种创建线程方法:
package demo1;
public class SubRunnable implements Runnable {
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(i + "run");
}
}
}
package demo1;
public class ThreadDemo {
public static void main(String[] args) {
SubRunnable sr1 = new SubRunnable();
Thread t1 = new Thread(sr1);
t1.start();
for (int i = 0; i < 50; i++) {
System.out.println(i + "main");
}
}
}
这种方式好处:
1.接口可以多实现,避免了单继承的局限性
2.线程和方法分离,更符合面向对象的特点
3.资源实现共享
这两种方式可以实用匿名内部类实现:
package demo1;
public class ThreadDemo {
public static void main(String[] args) {
// 继承方式
new Thread() {
public void run() {
System.out.println("1");
}
}.start();
// 实现接口方式
new Thread(new Runnable() {
public void run() {
System.out.println(2);
}
}).start();
}
}
线程的状态:
1.新建状态:new Thread()创建线程对象
2.运行状态:使用了start()方法进入运行状态
3.退出状态:run方法结束,或者调用了stop方法(已过时,不建议实用)
4.阻塞状态:有时候使用了start方法,但不一定立即运行,或者运行之后CPU由于一些原因不再分配,由运行状态转到阻塞状态
5.休眠状态:前边提到的sleep方法就是这种状态,也有可能转到阻塞状态或者运行状态
6.等待状态:wait方法,无限等待,notify方法可以唤醒线程,可能转到运行或阻塞状态
注意:受阻塞是等待CPU的资源,休眠等待是放弃CPU的执行
线程池的概念:
一个容器,存入多个线程,需要时候,拿出执行,
运行结束后线程再回到容器中,这种方式可以提高效率
实现线程池:
package demo1;
public class ThreadPoolRunnable implements Runnable {
public void run(){
System.out.println(Thread.currentThread().getName()+"线程提交任务");
//输出: pool-1-thread-1线程提交任务
// pool-1-thread-2线程提交任务
}
package demo1; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ThreadPoolDemo {
public static void main(String[] args) {
//调用工厂类的方法创建线程池
ExecutorService es1 = Executors.newFixedThreadPool(2);
es1.submit(new ThreadPoolRunnable());
es1.submit(new ThreadPoolRunnable());
//运行后不会停 es1.shutdown();//销毁线程池,不常用
}
}
实现线程的Callable接口方式:
它弥补了Runnable方式的缺陷:无法抛出异常,并且有返回值
使用方法和Runnable方式基本一致:
示例:
package demo1;
import java.util.concurrent.Callable;
public class ThreadPoolCallable implements Callable<String>{
public String call(){
return "a";
}
}
package demo1; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ThreadPoolDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService es1 = Executors.newFixedThreadPool(2);
Future<String>f1 = es1.submit(new ThreadPoolCallable());
String s1 = f1.get();
System.out.println(s1);
//得到返回值,输出a
}
}
简单应用:多线程异步计算
使用两个线程计算求和:
package demo1;
import java.util.concurrent.Callable;
public class GetSumCallable implements Callable<Integer> {
private int a;
public GetSumCallable(int a) {
this.a = a;
}
public Integer call() {
int sum = 0;
for (int i = 0; i <= a; i++) {
sum += i;
}
return sum;
}
}
package demo1; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ThreadPoolDemo {
public static void main(String[] args) throws Exception {
ExecutorService es1 = Executors.newFixedThreadPool(2);
Future<Integer> f1 = es1.submit(new GetSumCallable(100));
Future<Integer> f2 = es1.submit(new GetSumCallable(300));
System.out.println(f1.get());
System.out.println(f2.get());
es1.shutdown();
}
}
Java学习笔记44(多线程一:Thread类)的更多相关文章
- Java学习笔记31(IO:Properties类)
Properties类,表示一个持久的j集,可以存在流中,或者从流中加载 是Hashtable的子类 map集合的方法都能用 用途之一:在开发项目中,我们最后交给客户的是一个编译过的class文件,客 ...
- java学习笔记6--类的继承、Object类
接着前面的学习: java学习笔记5--类的方法 java学习笔记4--类与对象的基本概念(2) java学习笔记3--类与对象的基本概念(1) java学习笔记2--数据类型.数组 java学习笔记 ...
- [core java学习笔记][第四章对象与类]
4.3 用户自定义类 4.3.1 类数组的声明 需要两次new Employee[]=staff=new Employedd[3]; staff[0]=new Employedd(参数列表); sta ...
- java学习笔记(3)——对象与类(日期)
变量.类型.赋值.运算符等等: https://blog.csdn.net/common77zwq/article/details/81988676 1.概念: 面向对象程序设计OOP.类class. ...
- 【Todo】Java学习笔记 100==100 & Reflection API & Optional类详解 & DIP、IoC、DI & token/cookie/session管理会话方式
为什么1000 == 1000返回为False,而100 == 100会返回为True? Link Java Reflection API:Link Java8 Optional 类深度解析: L ...
- Java学习笔记(2)--- 对象和类入门,java包,this 和 super区别
1.对象和类(Object and class): 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作. 面对对象编程是java非常重要的一部分,作者本身之前学过c ...
- java学习笔记15--多线程编程基础2
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...
- java学习笔记14--多线程编程基础1
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...
- java学习笔记12--异常处理
java学习笔记系列: java学习笔记11--集合总结 java学习笔记10--泛型总结 java学习笔记9--内部类总结 java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 j ...
随机推荐
- Java POI操作Excel注意点
excel的行索引和列索引都是从0开始,而行号和列号都是从1开始 POI·操作excel基本上都是使用索引 XSSFRow对象的 row.getLastCellNum() 方法返回的是当前行最后有效列 ...
- 记号一下selenium+Firefox自动下载的参数
参考: https://blog.csdn.net/wxstar8/article/details/80782556 https://blog.csdn.net/xiaoguanyusb/articl ...
- DB2 公共表表达式(WITH语句的使用)
----start 说起WITH 语句,除了那些第一次听说WITH语句的人,大部分人都觉得它是用来做递归查询的.其实那只是它的一个用途而已,它的本名正如我们标题写的那样,叫做:公共表表达式(Commo ...
- [leetcode]67. Add Binary 二进制加法
Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...
- Sublime Text3快捷键大全
选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本. Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑.举个栗子:快速选中并更改所有相同的变量名.函数 ...
- IntelliJ IDEA常用快捷键(Mac)
Mac 键盘符号和修饰键说明 ⌘ ——> Command ⇧ ——> Shift ⌥ ——> Option ⌃ ——> Control ↩︎ ——> Return/Ent ...
- Python开发——数据类型【列表】
列表的定义 中括号[]内以逗号分隔开,按照索引,存放各种数据类型,每个位置代表一个元素 list_t = ['张三','Lucy',123] print(list_t) # ['张三', 'Lucy' ...
- 在URL地址中传值
URL: re_path('edit_teacher-(\d+).html', views.handle_edit_teacher), HTML: <a href='/edit_teacher- ...
- zeromq学习记录(一)最初的简单示例使用ZMQ_REQ ZMQ_REP
阅读zeromq guide的一些学习记录 zeromq官方例子 在VC下运行会有些跨平台的错误 我这里有做修改 稍后会发布出来 相关的代码与库 http://download.zeromq.org ...
- MybatisMapper 映射框架(增删改查 原始模式)
//增删改查 package TestDemo; import java.io.IOException; import java.io.InputStream; import java.util.Da ...