IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java多线程 -> 正文阅读

[Java知识库]java多线程

一,创建线程的方式一——继承Thread类,重写run方法

线程类:

public class MyThread extends Thread{//1,继承Thread类

	//2,重写run方法
	@Override
	public void run() {
		for(int i = 0;i<20;++i)
		{
			System.out.println("id:"+this.getId()+" name:"+this.getName()+" i="+i);
		}
	}
}

public class ThreadTest {
	public static void main(String[] args) {
		//3,创建子类对象
		MyThread myThread = new MyThread();
		//4,调用start()方法
		myThread.start();
		
		MyThread myThread2 = new MyThread();
		myThread2.setName("我的线程");
		myThread2.start();
	}
}

运行结果:
在这里插入图片描述
(1)获得线程Id和线程名称
①在Thread的子类中调用this.getId();this.getName();分别获得id和名称。——只适合继承Thread类的子类中

②使用Thread.currentThread().getId();Thread.currentThread().getName();的方式。——通用

(2)修改线程名称(线程id不可修改)
①调用线程对象的setName()方法。——需要在启动前修改
在这里插入图片描述

②构造函数,在类中添加带参构造函数用于设置线程名称
从源码可以看出,Thread类中具有在创建线程对象时设置线程名称的构造函数,如下图:
在这里插入图片描述
在这里插入图片描述
在程序中的用法:

   //用于设置线程名的构造函数
	public MyThread(String name)
	{
		super(name);
	}
		MyThread myThread2 = new MyThread("我的线程");
		myThread2.start();

二,创建线程的方式2——实现Runnable接口,重写run方法

public class MyRunnable implements Runnable {//1,实现Runnable接口

	//2,覆盖run方法
	@Override
	public void run() {
		for(int i = 0; i<10; ++i)
		{
			System.out.println("id:"+Thread.currentThread().getId()+" name"+Thread.currentThread().getName()+" i:"+i);
		}
	}

}
public class ThreadTest {
	public static void main(String[] args) {	
		//3,创建实现类的对象
		MyRunnable myrunnable = new MyRunnable();
		//4,创建线程对象
		Thread thread = new Thread(myrunnable,"我的线程1");
		//5,调用start()方法
		thread.start();
		
		Thread thread2 = new Thread(myrunnable,"我的线程2");
		thread2.start();
	}
}

匿名内部类:

	public static void main(String[] args) {	
		Runnable runnable = new Runnable(){
			@Override
			public void run() {
				for(int i=0;i<10;++i)
				{
					System.out.println("id:"+Thread.currentThread().getId()+" name:"+Thread.currentThread().getName()+" i:"+i);
				}				
			}
		};
		Thread thread = new Thread(runnable,"我的线程");
		thread.start();
	}

当这个对象只会创建一次线程时:

		new Thread(new Runnable(){
			@Override
			public void run() {
				for(int i=0;i<10;++i)
				{
					System.out.println("id:"+Thread.currentThread().getId()+" name:"+Thread.currentThread().getName()+" i:"+i);
				}				
			}
		},"我的线程").start();

三,创建线程的方式三——实现Callable接口,重写call()方法

public static void main(String[] args) {	
		Callable<Integer> callable = new Callable<Integer>() {

			private Integer sum = 0;
			@Override
			public Integer call() throws Exception {
				for(int i=0;i<10;++i)
				{
					sum+=i;
					System.out.println("id:"+Thread.currentThread().getId()+" name"+Thread.currentThread().getName()+" sum:"+sum);
				}
				return sum;
			}
		};
		
		FutureTask<Integer> task = new FutureTask<>(callable);
		
		Thread thread = new Thread(task);
		
		thread.start();
		
		Integer sum = 0;
		try {
			sum = task.get();
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(sum);
	}
}

Furture接口表示将要完成任务的结果,后期还有深入学习。

四,线程中常用方法

1,public static void sleep(long millis);
当前执行的线程主动停止运行一段millis毫秒的时间。

2,public static void yield();
当前执行的线程主动暂定。放弃时间片,回到就绪状态,等待下一次时间片。

3,public final void join();
允许其他线程加入当前线程中,将当前线程阻塞,直到加入的线程执行完毕。

4,线程对象.setPriority()getPriority()
设置线程的优先级和获得线程的优先级!

线程的优先级为1-10,优先级越高表示获得CPU机会越多,默认为5。

5,线程对象.setName()和getName()
设置线程的名称和获得线程的名称

6,线程对象.getId()
获得线程的名称

7,线程对象.isAlive()
判断线程是否终止

8,Thread.currentThread()
获得当前正在运行线程的对象

9,线程对象.setDaemon(true);
设置该线程为守护线程

线程:
①用户线程(前台线程)
②守护线程(后台线程)
.
如果程序中所有前台线程都执行完毕了,后台线程就会自动结束
垃圾回收器属于守护线程

五,线程安全

多线程并发访问临界资源,破坏了原子性而造成数据不一致。
在这里插入图片描述
在这里插入图片描述
以上代码两个线程thread和thread2公用了一个MyRunnable对象,而该类中有变量sum,即是两个线程共用一个变量sum,于是造成:
在这里插入图片描述
1,同步方式1——同步代码块

synchronized(sum)
{
	System.out.println("线程id:"+Thread.currentThread().getId()+" sum:"+sum);
	sum--;
}

对临界资源对象sum进行加锁,锁中的代码将具有原子性,要么都不执行,要么都执行。

synchronized(临界资源对象){//对临界资源对象加锁
//代码 (原子操作)
}
.
括号中的临界资源对象,需是引用 类型
Object o = new Object();创建的对象也可
可用this

运行结果:
在这里插入图片描述

2,同步方式2——同步方法

	synchronized void printSum()
	{
		while(sum>=0)
		{
				System.out.println("线程id:"+Thread.currentThread().getId()+" sum:"+sum);
				sum--;
		}
	}

相当于对当前对象(this)加锁
如果是静态方法,相当于对当前类加锁,即对MyRunnable.class加锁

3,锁

4,已知的线程安全的容器类
在这里插入图片描述
CopyOnWriteArraySet、CopyOnWriteArrayList、ArrayBolckingQueue、LinkedBlockingQueue、ConcurrentLinkedQueue和vector都是线程安全的容器,Vector的性能比较低,基本不用。

在这里插入图片描述
ConcurrentSkipListMap、ConcurrentHashMap是线程安全的。

六、线程池

线程是内存资源,即会占用内存,当系统创建很多线程时容易造成内存溢出,并且频繁的创建和销毁线程时会增加资源开销造成性能下降。

故,引入线程池,预先创建线程对象并存入线程池中,需要使用线程时从池中取线程对象,使用完后将线程对象归还至线程池,重用线程池中的线程对象,避免频繁的创建与销毁;线程池可设定线程分配的数量上限。

…(线程池这么重要的东西,不得在分一篇)

大概就梳理的这么多吧,都是挺基础的东西,但对我来说可是从0到有,从不知道多线程到了解了这么多,慢慢深入研究吧。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 19:22:40  更:2021-07-04 19:23:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/18 14:43:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码