多线程基础知识

多线程基础知识的学习
基本概念多线程的创建方式多线程的常用方法多线程的生命周期线程的安全问题解决线程的安全问题线程安全的单例模式之懒汉式线程中的死锁问题线程的通信

基本概念

    程序: 为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象;进程: 是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程:有它自身的产生、存在和消亡的过程—-生命周期;线程 : 进程可以进一步细化为线程,是程序内部的一条执行路径,一个程序可以有多条执行路径;

程序是静态的,进程是动态的;

进程作为资源分配单位,系统在运行时会为每个进程分配不同的内存区域;

线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器;

一个进程中的多个线程共享相同的内存单元/内存地址空间–它们从同一堆中分配对象,可以访问相同的变量和对象,这就是线程间的通信更加的简便、高效,但是多线程操作共享的系统资源可能带来安全隐患;

多线程的创建方式

面试题:创建多线程的方式有几种?
答:四种;
1). 继承Thread类的方式创建线程;
2). 实现Runnable接口创建线程;
3). 使用Callable和Future创建线程;
4). 使用线程池例如用Executor框架;

1.继承Thread类的方式创建线程:

public class Main01 {

public static void main(String[] args) {
//给主线程命名:Thread.currentThread()是获取当前线程
Thread.currentThread().setName("主线程");
//打印
System.out.println(Thread.currentThread().getName()+"线程执行了");
//创建一个线程
MyThread myThread = new MyThread();
//启动线程
myThread.start();
}
}

class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程执行了");
}
}
//输出
主线程线程执行了
Thread-0线程执行了

2.实现Runnable接口的方式创建线程:

public class Main02 {

public static void main(String[] args) {
//给main线程命名
Thread.currentThread().setName("主线程");
//打印
System.out.println(Thread.currentThread().getName()+"执行了");

//创建线程
MyRunnable myRunnable = new MyRunnable();
//将myRunnable传入Thread;类中
Thread thread = new Thread(myRunnable);
thread.start();
}
}

class MyRunnable implements Runnable{

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"执行了");
}
}
//输出
主线程线程执行了
Thread-0线程执行了

3.使用Callable和FutureTask创建线程

public class Main03 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建实现类
MyCallable myCallable = new MyCallable();
//创建FutureTask类,该类实现了Runnable接口;
FutureTask stringFutureTask = new FutureTask(myCallable);
//将创建的FutureTask的实例传递给Thread类,并启动线程
new Thread(stringFutureTask).start();

Object o = stringFutureTask.get();

System.out.println(o);

}
}
//MyCallable接口实现Callable接口,其中的call方法相当于我们的run方法
class MyCallable implements Callable{

@Override
public Object call() throws Exception {
int h = 0;
for(int i = 1; i <100; i++){
if(i % 2 == 0){
h+=i;
}
}
return Thread.currentThread().getName()+"求和为:--"+h;
}
}

4.使用线程池

public class Main04 {

public static void main(String[] args) {
//1.提供指定线程数量的线程池;
ExecutorService executorService = Executors.newFixedThreadPool(10);

//2.执行指定的线程操作,需要提供实现Runnable接口和Callable接口的实现类对象;
executorService.execute(new MyRunnable1());

//关闭连接池;
executorService.shutdown();

}
}
class MyRunnable1 implements Runnable {
@Override
public void run() {

System.out.println("这是使用线程池创建线程");

}
}
使用线程池的好处:
1.提高响应速度(减少了线程的创建时间)
2.降低了资源消耗(重复利用线程池中的线程,不需要每次都创建)
3.便于管理:
corePoolSize:核心池的大小
maximumPoolSize:最大线程数;
keepAliveTime:线程没有任务是最多保持多长时间后终止

多线程的常用方法

1.start():启动当前线程;调用当前线程的run();
2.run(): 通常需要重写Thread类中的此方法,将要执行的操作写入该方法中;
3.currentThread(): 静态方法,返回执行当前代码的线程;
4.getName():获取当前线程的名字;
5.setName():设置当前线程的名字;
6.yield():释放当前cpu的执行权;
7.join():在线程A中调用线程B的join(),此时线程A就会进入阻塞状态,直到线程B完全执行完以后,线程A才结束阻塞状态;
8.stop():已过时,当执行此方法是,强制结束当前线程;
9.sleep(long millitime) : 使当前线程睡眠指定的毫秒数,在此期间,该线程处于阻塞状态;
10. isAlive(): 判断当前线程是否存活;

多线程的生命周期

多线程基础知识

线程的安全问题

1.多个线程执行的不确定性造成执行结果的不稳定
2.多个线程对账本的共享,会造成操作的不完整性,会破坏数据;

解决线程的安全问题

解决线程安全的方式有几种?
答:3种;
1.同步代码块—synchronized(同步监视器){需要被同步的代码}

public class SYNdemo01 {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);

thread1.start();
thread2.start();

}
}
class MyRunnable implements Runnable{
private int x = 150;
@Override
public void run() {
while (true){

synchronized (this){
if(x>0){
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口卖出了:"+x+"号票");
x--;
}else{
break;
}
}
}
}
}
synchronized(锁){需要被同步的代码}
1.操作共享数据的代码,即需要被同步的代码;
2.共享数据,多个线程同时操作的变量,比如我们现实中的火车票
3.同步监视器:俗称:锁,任何一个类的对象,都可以充当锁对象;
要求:多个线程必须要共用一把锁,即这个锁对象在多线程操作时必须是同一个锁对象;

2.同步方法—被synchronized修饰的方法

public class SYNdemo01 {

public static void main(String[] args) {

MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
Thread thread2 = new Thread(myRunnable);

thread1.start();
thread2.start();

}
}
class MyRunnable implements Runnable{
private int x = 150;
@Override
public void run() {
while (true){

loket();
if(x<=0){
break;
}

}
}

//同步方法
public synchronized void loket(){
if(x>0){
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口卖出了:"+x+"号票");
x--;
}

}
}

3.Lock锁解决线程安全问题
Lock锁是JDK5.0后加入的,是一个接口,比较常用的是ReentrantLock类,他拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁;

public class LockSuo {

public static void main(String[] args) {
Window window = new Window();
Thread thread1 = new Thread(window);
Thread thread2 = new Thread(window);

thread1.start();
thread2.start();
}
}

class Window implements Runnable{

private static int x = 150;
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
while (true){
try{
reentrantLock.lock();

if(x>0){

try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"窗口出售了:"+x+"号票");
x--;
}else{
break;
}
}finally {
reentrantLock.unlock();
}
}
}
}

线程安全的单例模式之懒汉式

class BankTest{
private static BankTest bankTest;

private BankTest(){

}
public static BankTest getBankTest(){
synchronized (BankTest.class) {
if (bankTest == null) {

bankTest = new BankTest();
}
}
return bankTest;
}
}

线程中的死锁问题

死锁: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁;
死锁出现后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续;
死锁演示:

public class SYNdemo02 {
public static void main(String[] args) {

StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();

new Thread(){
@Override
public void run() {
synchronized (s1){
s1.append("a");
s2.append("1");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2){
s1.append("b");
s2.append("2");

System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
new Thread(){
@Override
public void run() {
synchronized (s2){
s1.append("c");
s2.append("3");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1){
s1.append("d");
s2.append("4");

System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
}
}

线程的通信

例题:交替打印1-100;线程1和线程2交替打印;

public class JT {
public static void main(String[] args) {

Number number = new Number();
Thread thread1 = new Thread(number);
Thread thread2 = new Thread(number);

thread1.start();
thread2.start();
}
}

class Number implements Runnable {
private static int x = 1;

@Override
public void run() {
while (true) {
synchronized (this) {
if (x <= 100) {
notify();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "打印了:" + x);
x++;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}

}

}
}

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

多线程基础知识

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » 多线程基础知识
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏