java学习的第八天:
文章内容主要来源为元动力科技,我个人觉得非常好,这里是他们的网站 网站链接
第六章:线程:
6.1线程和进程:
线程:一个正在执行中的程序就是一个进程,系统会为这个进程发配独立的【内存资源】。进程是程序的一次执行过程,它有自己独立的生命周期,它会在启动程序时产生,运行程序时存在,关闭程序时消亡。
进程:线程是由进程创建的,是进程的一个实体,是具体干活的人,一个进程可能有多个线程。线程不独立分配内存,而是共享进程的内存资源,线程可以共享cpu的计算资源。
知识补充:
-
物理CPU就是计算机上实际安装的CPU,就是主板上实际插入的CPU数量。 -
物理CPU内核,每颗物理CPU可以有1个或者多个物理内核,通常每颗物理CPU的内核数都是固定的,单核CPU就是有1个物理内核,我这个电脑有八颗 -
逻辑CPU,操作系统可以使用逻辑CPU来模拟真实CPU。在没有多核处理器的时候,一个物理CPU只能有一个物理内核,而现在有了多核技术,一个物理CPU可以有多个物理内核,可以把一个CPU当作多个CPU使用,没有开启超线程时,逻辑CPU的个数就是总的CPU物理内核数。然而开启超线程后,逻辑CPU的个数就是总的CPU物理内核数的两倍。
6.2线程的创建:
(1.)继承Thread类重写run方法:run和start【文章】
步骤:
1.定义类继承Thread;
2.重写Thread类中的run方法;(目的:将自定义代码存储在run方法,让线程运行)
3.调用线程的start方法:(该方法有两步:启动线程,调用run方法)
package com.itheima.example18;
public class UseThread {
public static void main(String[] args) {
System.out.println(1);
new MyTask().start();
System.out.println(3);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(4);
}
static class MyTask extends Thread{
@Override
public void run(){
System.out.println(2);
}
}
}
输出结果:
(2.)实现Runnable接口:(Runnable和Thread的区别)【文章】
步骤:
1.创建任务: 创建类实现Runnable接口
2.使用Thread 为这个任务分配线程
3.调用线程的start方法
package com.itheima.example18;
public class UseRunnable {
public static void main(String[] args) {
System.out.println(1);
new Thread(new Task()).start();
System.out.println(3);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(4);
}
static class Task implements Runnable{
public void run(){
System.out.println(2);
}
}
}
(3.) 使用Lmmabda表达式:
package com.itheima.example18;
public class UseRunnable {
public static void main(String[] args) {
System.out.println(1);
new Thread(()-> System.out.println(2)).start();
System.out.println(3);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(4);
}
}
(4.)有返回值的线程:
package com.itheima.example18;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;
public class UseCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println(2);
FutureTask<Integer> futureTask=new FutureTask<>(new Task());
System.out.println(3);
new Thread(futureTask).start();
System.out.println(4);
int result=futureTask.get();
System.out.println(5);
System.out.println(result);
System.out.println(6);
}
static class Task implements Callable <Integer>{
public Integer call() throws Exception{
Thread.sleep(2000);
return 1;
}
}
}
输出结果:
多线程计算从一加到一亿:
代码:
package com.itheima.example18;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;
public class UseCallable implements Callable<Long>{
private int from;
private int to;
public UseCallable() {
}
public UseCallable(int from, int to) {
this.from = from;
this.to = to;
}
@Override
public Long call() throws Exception{
Long res=0L;
for(int i=from;i<to;i++){
res+=i;
}
return res;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start=System.currentTimeMillis();
long res=0L;
for(int i=0; i<100000000;i++){
res+=i;
}
long end=System.currentTimeMillis();
System.out.println(end-start);
System.out.println(res);
start=System.currentTimeMillis();
res=0L;
FutureTask[] futureTasks=new FutureTask[5];
for(int i=0; i<5;i++){
FutureTask<Long> task=new FutureTask<>(new UseCallable(i*20000000,(i+1)*20000000));
new Thread(task).start();
futureTasks[i]=task;
}
for(int i=0;i<5;i++) {
Long sum=(long)futureTasks[i].get();
res+=sum;
}
end=System.currentTimeMillis();
System.out.println(end-start);
System.out.println(res);
}
}
6.3 守护线程
Java提供两种类型的线程:用户线程 和守护程序线程 。守护线程旨在为用户线程提供服务,并且仅在用户线程运行时才需要
守护线程对于后台支持任务非常有用,例如垃圾收集,释放未使用对象的内存以及从缓存中删除不需要的条目。
优先级:守护线程的优先级比较低,用于为系统中的其它对象和线程提供服务。
设置:通过setDaemon(true)来设置线程为“守护线程”;将一个用户线程设置为
守护线程的方式是在 线程对象创建 之前 用线程对象的setDaemon方法。
package com.itheima.example18;
public class Deamo {
public static void main(String[] args) {
Thread T1=new Thread(()->{
int count=10;
Thread T2=new Thread(()->{
while(true){
ThreadUtils.sleep(300);
System.out.println("我是个守护线程!");
}
});
T2.setDaemon(true);
T2.start();
while(count>0){
ThreadUtils.sleep(200);
System.out.println("我是用户线程");
count--;
}
System.out.println("用户线程结束----------------------------------------------");
});
T1.start();
}
}
输出结果:
6.4 线程的生命周期;
我们在Thread类中发现了一个内部枚举类,这个State就可以表示一个线程的生命周期:
我找不到这个state(菜狗),所以大家可以看下边链接里的的文章。
文章链接
下面我们弄一下join方法
package com.itheima.example18;
public class Text {
public static void main(String[] args) {
Thread t1=new Thread(()->{
for(int i=0;i<10;i++){
ThreadUtils.sleep(300);
System.out.println("这是线程1------------");
}
});
Thread t2=new Thread(()->{
for(int i=0;i<10;i++){
ThreadUtils.sleep(300);
System.out.println("这是线程2------------");
}
});
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("____--------------------------____");
}
}
输出结果:
join()方法的本意是阻塞主线程,直到t1线程和t2线程执行完毕后继续执行主线程;
|