Java小记——多线程01

目录

进程的概述和多进程的意义

线程的概述和多线程的意义

JVM运行原理以及JVM启动的线程探讨

实现多线程

方式一 继承Thread类

Thread类的基本获取和设置方法

设置和获取线程优先级

线程休眠

加入线程

礼让线程

守护线程

中断线程

方式二 实现Runnable接口  

方式三  实现 Callable 接口


进程的概述和多进程的意义

进程概述

什么是进程呢?通过任务管理器我们就可以看到进程的存在。

概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。

每一个进程都有它自己的内存空间和系统资源。

多进程的意义

单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音

乐进程),

所以我们常见的操作系统都是多进程操作系统。比如:Windows,Mac和Linux等,能在同一个时

间段内执行多个任务。

对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。

因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,

所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。多进程的作用不是提高执行速

度,而是提高CPU的使用率。

线程的概述和多线程的意义

什么是线程

在一个进程内部又可以执行多个任务,而这每一个任务我们就可以看成是一个线程。是程序使用

CPU的基本单位。所以,进程是拥有资源的基本单位, 线程是CPU调度的基本单位。

多线程有什么意义呢?

多线程的作用不是提高执行速度,而是为了提高应用程序的使用率。

那么怎么理解这个问题呢?

我们程序在运行的使用,都是在抢CPU的时间片(执行权),如果是多线程的程序,那么在抢到

CPU的执行权的概率应该比较单线程程序抢到的概率要大.那么也就是说,CPU在多线程程序

中执行的时间要比单线程多,所以就提高了程序的使用率.但是即使是多线程程序,那么他们

中的哪个线程能抢占到CPU的资源呢,这个是不确定的,所以多线程具有随机性.

并发:多个任务交替执行,不是真正意义上的同时执行,只是交替的速度很快你感觉在同时执行。

这就是Java中多个线程并发执行。

并行:真正意义上的同时执行,多个任务同时执行

一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行

不同的任务。

JVM运行原理以及JVM启动的线程探讨

Java程序运行原理

Java.exe 命令会启动java虚拟机,启动JVM,等于启动了一个应用程序,也就是启动了一个进程。

该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。

所以 main方法运行在主线程中。

JVM的启动是多线程的吗:        JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。

实现多线程

方式一 继承Thread类

1.定义一个类,继承 Thread

2.重写 Thread 类的run方法

3.创建你定义的这个类对象,调用start()方法启动线程

public class MyThread extends Thread {

    //run方法里面的代码将来你让你创建的线程一旦启动,就会过来执行。
    @Override
    public void run() {
        //这里面的代码就是有线程过来执行的代码,一般我在子线程里面做一些耗时的操作
        for (int i = 0; i < 100; i++) {
            System.out.println("子线程执行的代码:" + i);
        }
    }
}



MyThread th = new MyThread();
        //th.run(); //这样不是开启了线程,你这是创建了一个对象,调用了run方法,没有新的线程开启。

        th.start(); //正确开启线程的方法
        // th.start(); 同一个线程对象不要重复调用 start()

        MyThread th2 = new MyThread();

        th2.start();


Thread类的基本获取和设置方法

public final String getName()//获取线程名称

public final void setName(String name)//设置线程名称

public static Thread currentThread()//获取当前执行的线程

 System.out.println("主线程中代码AAA");
        //currentThread();获取当前执行的线程对象
        Thread thObj = Thread.currentThread();
        thObj.setName("主线程");
        System.out.println(thObj.getName());
        //在这个结点处开启一个子线程
        MyThread th1 = new MyThread();
        th1.setName("范冰冰");

线程的执行

假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,

线程只有得到 CPU时间片,也就是使用权,才可以执行指令。那么Java是如何对线程进行调用的

呢?

抢占式调度模型   优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。 

Java使用的是抢占式调度模型。

设置和获取线程优先级

public final int getPriority() //获取线程的优先级

public final void setPriority(int newPriority)//设置线程的优先级

线程的优先级的大小仅仅表示这个线程被CPU执行的概率增大了.但是我们都知道多线程具有随机

th1.setPriority(Thread.MAX_PRIORITY);
        int priority = th1.getPriority();
        System.out.println("th1的优先级:" + priority);
        th1.start();

        //在这个结点处开启一个子线程
        MyThread th2 = new MyThread();
        th2.setName("刘亦菲");
        th2.setPriority(Thread.MIN_PRIORITY);
        int priority1 = th2.getPriority();
        System.out.println("th2的优先级:" + priority1);
        th2.start();

线程休眠

public static void sleep(long millis) 线程休眠

有异常要处理

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread th = new MyThread();
        th.start();

        //让当前线程休眠
        Thread.sleep(1000 * 3);
        System.out.println("主线程的代码");
        System.out.println("主线程的代码");
        System.out.println("主线程的代码");
     
    }
}


class MyThread extends Thread {
    @Override
    public void run() {
        try {
            //让当前线程进行休眠
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 100; i++) {
            System.out.println("子线程执行的代码:" + i);
        }
    }
}

加入线程

public final void join()

等待该线程执行完毕了以后,其他线程才能再次执行

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread th1 = new MyThread("刘备");
        MyThread th2 = new MyThread("关羽");
        MyThread th3 = new MyThread("张飞");
        th1.start();
        th1.join();
        th2.start();
        th2.join();
        th3.start();
        th3.join();

        //join()在线程开启之后,调用,可以把多个线程并发执行,变为串行。


    }
}


 class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName() + "-子线程执行的代码:" + i);
        }
    }
}

礼让线程

public static void yield():    暂停当前正在执行的线程对象,并执行其他线程。

效果好像不太明显.

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread th1 = new MyThread("刘备");
        MyThread th2 = new MyThread("关羽");
        th1.start();
        th2.start();

       
    }
}


 class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            System.out.println(this.getName() + "-子线程执行的代码:" + i);
            Thread.yield(); //线程礼让
        }
    }
}

守护线程

public final void setDaemon(boolean on)

setDaemon(true),设置线程为守护线程。

thread.setDaemon(true)必须在thread.start()之前设置。

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        Thread main = Thread.currentThread();
        main.setName("刘备");
        for (int i = 0; i < 10; i++) {
            System.out.println(main.getName() + "i");
        }

        MyThread th2 = new MyThread("关羽");
        MyThread th3 = new MyThread("张飞");
        //设置守护线程
        th2.setDaemon(true);
        th2.start();
        //设置守护线程
        th3.setDaemon(true);
        th3.start();

    }
}


class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(this.getName() + "-子线程执行的代码:" + i);
        }
    }
}





刘备i
刘备i
刘备i
刘备i
刘备i
刘备i
刘备i
刘备i
刘备i
刘备i
关羽-子线程执行的代码:0
张飞-子线程执行的代码:0
张飞-子线程执行的代码:1
张飞-子线程执行的代码:2
张飞-子线程执行的代码:3
张飞-子线程执行的代码:4

中断线程

public final void stop():        停止线程的运行

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread th = new MyThread("线程A");
        th.start();
        Thread.sleep(5);
        th.stop(); //强制停止线程 主线程睡5秒 再停止

    }
}


class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(this.getName() + "-子线程执行的代码:" + i);
        }
    }
}

public void interrupt():        中断线程(这个翻译不太好),查看API可得当线程调用wait(),sleep(long

time)方法的时候处于阻塞状态,可以通过这个方法清除阻塞

public class MyTest {
    public static void main(String[] args) throws InterruptedException {
        MyThread th = new MyThread("线程A");
        th.start();
        th.interrupt(); //清除线程阻塞的状态 停止支线的睡眠
    }
}



public class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 1000; i++) {
            System.out.println(this.getName() + "-子线程执行的代码:" + i);
        }
    }
}

方式二 实现Runnable接口  

这种方式扩展性强 实现一个接口 还可以再去继承其他类

1.定义一个类,实现  Runnable 接口

2.重写run方法

3.创建定义的这个类的对象

4.new Thread 把这个类的对象作为参数,传过来

5.  调用start()方法启动

MyRunnable myRunnable = new MyRunnable();

        Thread th = new Thread(myRunnable);
        th.setName("线程A");
        th.start();



class MyRunnable implements Runnable {

    //void run()
    // 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "-" + i);
        }
    }
}

方式三  实现 Callable 接口

相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。

执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。  FutureTask 是  Future

接口的实现类

1.创建一个类实现Callable 接口

2.创建一个FutureTask类将Callable接口的子类对象作为参数传进去

3.创建Thread类,将FutureTask对象作为参数传进去

4.开启线程

public class MyTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程的第三种方式
        MyCallable myCallable = new MyCallable();
        //可使用 FutureTask 包装 Callable 或 Runnable 对象。因为 FutureTask 实现了 Runnable,所以可将 FutureTask 提交给 Executor 执行。
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        Thread th = new Thread(futureTask);
        th.start();
        //Thread.sleep(100);
        Integer integer = futureTask.get();
        System.out.println(integer);
    }
}


public class MyCallable implements Callable<Integer> {
    //call方法也是线程将来执行的方法
    @Override
    public Integer call() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
        return 100;
    }
}

接入第三方登录是让用户方便快捷地使用已有账号登录你的网站或应用程序,提高用户体验的一种方式。本文将介绍如何使用 PHP 实现微信公众号第三方登录。 1. 获取微信授权 首先,需要获取微信用户的授权。具体步骤如下: 1)引导用户打开微信授权页面: ```php $appid = 'your_appid'; $redirect_uri = urlencode('http://yourdomain.com/callback.php'); $scope = 'snsapi_userinfo'; $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=$scope&state=STATE#wechat_redirect"; header("Location: $url"); ``` 其中,`$appid` 是你的微信公众号的 AppID,`$redirect_uri` 是授权后回调的 URL,`$scope` 是授权作用域,可以是 `snsapi_base` 或 `snsapi_userinfo`,`$state` 是自定义参数,用于防止 CSRF 攻击。 2)获取授权码: 用户同意授权后,会重定向到 `$redirect_uri` 指定的 URL,带上授权码 `code` 和 `state` 参数。 ```php $code = $_GET['code']; $state = $_GET['state']; ``` 3)获取 access_token 和 openid: 使用授权码 `code` 获取 `access_token` 和 `openid`。 ```php $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code"; $response = file_get_contents($access_token_url); $result = json_decode($response, true); $access_token = $result['access_token']; $openid = $result['openid']; ``` 其中,`$secret` 是你的微信公众号的 AppSecret。 2. 获取用户信息 获取到 `access_token` 和 `openid` 后,可以使用以下代码获取用户信息: ```php $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN"; $response = file_get_contents($userinfo_url); $userinfo = json_decode($response, true); ``` 其中,`$userinfo` 包含用户的昵称、头像等信息。 3. 将用户信息保存到数据库 最后,将获取到的用户信息保存到数据库中,以便下次使用时快速登录。 ```php // 连接数据库 $con = mysqli_connect('localhost', 'username', 'password', 'database'); mysqli_set_charset($con, "utf8"); // 查询用户是否已存在 $sql = "SELECT * FROM users WHERE openid='$openid'"; $result = mysqli_query($con, $sql); if (mysqli_num_rows($result) == 0) { // 用户不存在,插入新用户信息 $nickname = mysqli_real_escape_string($con, $userinfo['nickname']); $headimgurl = mysqli_real_escape_string($con, $userinfo['headimgurl']); $sql = "INSERT INTO users (openid, nickname, headimgurl) VALUES ('$openid', '$nickname', '$headimgurl')"; mysqli_query($con, $sql); } // 保存用户登录状态 $_SESSION['openid'] = $openid; ``` 以上就是使用 PHP 实现微信公众号第三方登录的步骤。需要注意的是,为了确保安全性,应该对用户输入的数据进行过滤和验证,防止 SQL 注入和 XSS 攻击等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jmh-Ethereal

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值