当前位置:   article > 正文

【JUC并发编程1】GitHub使用教程:从GitHub上拉取文件到本地,从本地上传文件到GitHub,使用IDEA拉取和推送,管理项目版本_github clone到本地

github clone到本地

博客背景:最近在做项目,经常会使用到GitHub,常用的需求包含:拉取远端GitHub文件保存到本地,从本地上传文件到GitHub仓库等等...命令经常会忘,因此整理一篇博客,

一、从GitHub上拉取文件到本地

使用命令:git clone

git clone 仓库地址

操作步骤:

第1步:进入到本地机中想要存储文件的目录中,右键,点击“Git Bash Here”

第2步:在GitHub上找到想要拉取的项目,点击Code,复制仓库地址,在git bash中输入"git clone 仓库地址"

 

如果出现下面错误:

可以输入下面代码,关闭证书校验:

git config --global http.sslVerify false

第3步:成功将资源从GitHub下载到本地文件夹,检查项目的完整性

二、从本地上传文件到GitHub

使用命令:git -c http.sslVerify=false push -u 仓库地址 分支名称

操作步骤:

 1.GitHub上创建新Repository

 在GitHub上创建名为springcloud-config的新Repository:

复制HTTPS地址,比如:git@github.com:pbjlovezjy/springcloud-config.git

2.推送本地仓库的项目到GitHub

在spring-config文件夹下的空白处单击右键,进入Git Bash

然后输入:git -c http.sslVerify=false push -u 仓库地址 分支名称

然后会弹出一个界面,选择 sign in with your browser,选择授权git系统,然后输入密码即可:

 

可以直接将文件夹内容提交至仓库:

三、更新GitHub仓库

假如我们现在删掉了本地文件夹里的README.md,我们想把这一修改同步到GitHub上,要如何做呢?

首先我们输入:git add .  (注意最后有个点)将所有修改的内容放入缓冲区:

然后输入:git commit -m '随便填写'

即可实现GitHub同步本地文件夹的内容。

假设我们现在修改了GitHub上的内容,添加了一个README.mdd文件夹:

 

此时,我们本地没有README.md文件,假如我们想同步远程仓库和本地:

只需要输入:git -c http.sslVerify=false pull --rebase origin master  

文件就被我们同步到了本地:

四、创建秘钥并设置

 第3步: 如果报错,需要创建并设置秘钥,见第四节

解释:如果想从GitHub的仓库中拉取文件到本地,需要上报自己的用户名、邮箱、密码等信息,这些信息会被存储为秘钥,作为访问GitHub的权限。

假如GitHub的用户名为:aabbccdd

密码:11223344

邮箱:12345@qq.com

第1步:打开Git bash设置用户名和邮箱

git config --global user.name "填你GitHub的用户名"

git config --global user.email "填你自己GitHub注册的邮箱"

  1. 示例如下:
  2. git config --global user.name "aabbccdd"
  3. git config --global user.email "12345@qq.com"

第2步:在Git Bash中输入以下代码,创建密钥:

1. 生成新的SSH密钥对(这一步是生成私钥):ssh-keygen -t rsa -b 4096 -C "你的邮箱"

示例:sh-keygen -t rsa -b 4096 -C "12345@qq.com"

2. 启动 SSH agent:eval "$(ssh-agent -s)"

3.添加你的私钥到SSH agent中:ssh-add ~/.ssh/id_rsa

4.复制公钥到剪贴板:clip < ~/.ssh/id_rsa.pub

公钥如下:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzEFpg4hNhzVRdmq/9At/hEealmjiprYUWFfkvuGSdU9PFQokWTLwOeR6z8yVjn0VrDFIGIyQ9q805Clcev1VqGN9CAy50adBTamW3mV1U8twTWS7VNc89WidA5OK5HyfL4xkuSg/NaOtOjj0m7+31+w3JANgavFjQaUi03peuGaCnp3xVsFWFO1r1msNTw0QwRnAPERwA3/w1jT7gNcJ/wS3yHJiNbKpwbJcLKAUJUFsijJ80C25b4/0jSjKyBl+W9ctDMW/2gTUMoMCFXiXgVHhdLJcbyHaqwC3xXP0hi8K20Yaqr4f8vxxEw3Wnfn/5Dzj4fZ24saMwff4RV8HwJ8BrQx+4la6RQhLYrWWCay6AA3+2jawhW/eW6FFnnywr4GnRnVXcc0F3iLlnEfPW5qOdLrG903vjL9xYe3bty8CTWRsF1ruTI2PjD06Om0hPK9mvTCPnoDzBktlsVX907qNaCVqjbwpfgtHae0fEDIWZXCkBaqaYvOm9wL5cPD0F6R9CqDs6BtrI4HSrh9tUvBKO9xHnFLAF2BLHuYcrzU62M1KGzLln4kPC9hlh8pMoxqQwkfccz3Z0F84b7q5ppg3PutoLfb+gLyCTfOTGKjuw3DWFaYPalGCYdQAPchsp8DylAnv4pecxGH79XnbZ46ExjkQ3znnotkPDqN/TIxfGaB7hQ== 3499045941@qq.com

第3步:打开GitHub粘贴密钥,完成关联:

点击右上角的头像,选择 "Settings":

在左侧菜单中选择 "SSH and GPG keys":

 

点击 "New SSH key":

在 "Title" 字段中,为你的密钥添加一个描述性的名称:

在 "Key" 字段中,粘贴你之前复制的公钥:

点击 "Add SSH key":

简单解释原理:私钥是存储在你自己本地电脑上的,公钥是放在GitHub上的,通过私钥来匹配公钥,使得本地机具有访问GitHub的权限。

五、使用IDEA拉取和推送

一、从Gitee上拉取文件到本地

二、从本地上传文件到Gitee

1.Gitee上创建新仓库

 

2.推送本地仓库的项目到Gitee

比如我现在想把JUC高并发这个文件夹下的JUCdemo项目上传到Gitee上。

1. 首先要进行Git的全局设置:

  1. git config --global user.name "这里填你的用户名"
  2. git config --global user.email "这里填你的邮箱"

2. 然后要创建git仓库:

选取一个本地git仓库所在的位置,可以是任意的文件夹。 

mkdir 仓库名称

 输入上面命令后会在当前文件夹下新建一个本地仓库,如下图:

3.仓库初始化

这一步包含下面3步:

进入仓库:

cd 仓库名

初始化仓库:

git init

 创建README.md文件(可选)

touch README.md

4.上传文件到本地仓库

比如:我想要上传的是JUCdemo文件,我需要先把JUCdemo文件给复制到本地仓库里,如下图:

然后输入下面命令,这个命令是将当前文件夹下的内容全部存入到缓冲区:

git add .

最后输入下面这个命令,这个命令可以把缓冲区中的数据提交到本地仓库:

git commit -m "提交名称"

注意,此时只是将数据提交到仓库的历史记录中,可以通过上面设定的“提交名称”来找到每一次提交的记录。

5.设置远程仓库

设置远程仓库的地址,输入如下命令:

git remote add origin 远程仓库地址

这里的origin指向的是Gitee仓库的原始位置(URL),相当于远程仓库的坐标,通过这个坐标可以定位到远程仓库。 

 

6.提交本地仓库数据到远程仓库

输入下面的命令,将本地仓库的内容提交到远程仓库:

git push origin master

分支在Git中用于隔离工作环境,不同的分支之间不会相互影响,能够独立工作。

上面这段代码的意思大概是:推送本地仓库的数据(git push -u)到远程仓库(名字为origin)的某个分支(默认分支名称)。

总结一下:想把本地的项目推送到Gitee上,流程:首先要把项目保存到本地仓库,然后再从本地仓库推送到远程仓库。 

三、更新Gitee仓库

创建分支

git branch "分支名称"

推送本地仓库数据到分支:

git push -u origin "分支名称"

四、使用IDEA拉取和推送

P226 ScheduledThreadPoolExecutor 定时执行

ScheduledThredPoolExecutor可以定时执行任务。

假如设置每隔1秒执行一次,因为休眠时间是2秒,所以会2秒执行一次。

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) {
  4. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  5. log.debug("start...");
  6. pool.scheduleAtFixedRate(()->{
  7. log.debug("running...");
  8. sleep(2);
  9. },2,1,TimeUnit.SECONDS);
  10. }
  11. }

每次任务开始的时间是从上一次任务结束时间点开始,睡眠时间+延迟时间:

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) {
  4. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  5. log.debug("start...");
  6. pool.scheduleWithFixedDelay(()->{
  7. log.debug("running...");
  8. sleep(2);
  9. },1,1,TimeUnit.SECONDS);
  10. }
  11. }

P227 正确处理线程池异常

方法1:用try-catch块捕获。

方法2:用submit方法然后返回为一个Future对象

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) throws ExecutionException, InterruptedException {
  4. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
  5. Future<Boolean> f = pool.submit(() -> {
  6. log.debug("task1");
  7. int i = 1 / 0;
  8. return true;
  9. });
  10. log.debug("result:{}", f.get());
  11. }
  12. }

如果没有异常返回true,有异常返回错误。 

P228 线程池应用 定时任务

使用now来计算当前时间,使用time来计算目标时间,使用initialDelay来计算距离第1次执行的时间,period用来设置每次执行的时间间隔。

  1. public class Test3 {
  2. public static void main(String[] args) {
  3. //获取当前时间
  4. LocalDateTime now = LocalDateTime.now();
  5. System.out.println(now);
  6. //获取周四时间
  7. LocalDateTime time = now.withHour(12).withMinute(3).withNano(0).with(DayOfWeek.SUNDAY);
  8. //如果当前时间>本周周四,必须找到下周周四
  9. if(now.compareTo(time)>0){
  10. time = time.plusWeeks(1);
  11. }
  12. System.out.println(time);
  13. long initialDelay = Duration.between(now,time).toMillis();
  14. long period = 1000;
  15. ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
  16. pool.scheduleAtFixedRate(()->{
  17. System.out.println("running...");
  18. },initialDelay,period, TimeUnit.MILLISECONDS);
  19. }
  20. }

P229 线程池应用 定时任务 测试

下图是效果:

P230 tomcat 线程池

LiMitLatch:用来限流,控制最大连接数,避免服务器被压垮。

Acceptor:负责接收新的socket连接

Poller:监听Socket channel连接上是否有可读的事件发生。一旦可读,封装一个任务对象socketProcessor提交给Executor线程池处理。

Executor线程池中的工作线程(worker)最终负责处理请求。

Tomcat线程池扩展了ThreadPoolExecutor,行为稍有不同:

P231 tomcat 线程池 配置

P232 forkjoin 概念

P233 forkjoin 使用

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) throws ExecutionException, InterruptedException {
  4. ForkJoinPool pool = new ForkJoinPool(4);
  5. System.out.println(pool.invoke(new MyTask(5)));
  6. }
  7. }
  8. @Slf4j(topic = "c.MyTask")
  9. //1~n之间整数的和
  10. class MyTask extends RecursiveTask<Integer>{
  11. private int n;
  12. public MyTask(int n) {
  13. this.n = n;
  14. }
  15. @Override
  16. public String toString(){
  17. return "(" + n + ")";
  18. }
  19. @Override
  20. protected Integer compute(){
  21. //终止条件
  22. if(n==1) {
  23. log.debug("join(){}",n);
  24. return 1;
  25. }
  26. MyTask t1 = new MyTask(n - 1);
  27. t1.fork();//让一个线程去执行此任务
  28. log.debug("fork(){}+{}",n,t1);
  29. int result = n + t1.join();
  30. log.debug("join(){}+{}",n,result);
  31. return result;
  32. }
  33. }

中间会用到多线程来执行任务的拆分和合并:

P234 forkjoin 任务拆分优化

P235 aqs 概述

aqs的全称是:AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架。

其它同步器工具都是作为aqs的实现子类。

提供阻塞式锁,更类似于悲观锁。

特点:

1.用state属性来表示资源的状态,分为独占模式和共享模式,独占式式只有一个线程能够访问资源,共享式式允许多个线程访问资源。

2.提供了基于FIFO的等待队列,类似于Monitor的EntryList。

3.条件变量来实现等待、唤醒机制,支持多个条件变量,类似于Monitor的WaitSet。

子类主要实现了下面这些方法:

tryAcquire

tryRelease

tryAcquireShared

tryReleaseShared

isHeldExclusively

P236 aqs 自定义锁

不可重入锁,本线程加了锁,下次还是同一个线程来了不能重复加。

  1. //自定义锁(不可重入锁)
  2. class MyLock implements Lock{
  3. //独占锁,同步器类
  4. class Mysync extends AbstractQueuedSynchronizer{
  5. @Override
  6. protected boolean tryAcquire(int arg) {
  7. if(compareAndSetState(0,1)){//其它线程可能也想修改状态
  8. //加上了锁,并设置owner为当前线程
  9. setExclusiveOwnerThread(Thread.currentThread());
  10. return true;
  11. }
  12. return false;
  13. }
  14. @Override
  15. protected boolean tryRelease(int arg) {
  16. setExclusiveOwnerThread(null);
  17. setState(0);
  18. return true;
  19. }
  20. @Override
  21. protected boolean isHeldExclusively() {
  22. return getState()==1;
  23. }
  24. public Condition newCondition(){
  25. return new ConditionObject();
  26. }
  27. }
  28. private Mysync sync = new Mysync();
  29. public MyLock() {
  30. super();
  31. }
  32. @Override //加锁,加锁不成功会放入队列等待
  33. public void lock() {
  34. sync.acquire(1);
  35. }
  36. @Override //加锁,可打断
  37. public void lockInterruptibly() throws InterruptedException {
  38. sync.acquireInterruptibly(1);
  39. }
  40. @Override //尝试加锁,只会尝试一次
  41. public boolean tryLock() {
  42. return sync.tryAcquire(1);
  43. }
  44. @Override //尝试加锁,带超时时间
  45. public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
  46. return sync.tryAcquireNanos(1,unit.toNanos(time));
  47. }
  48. @Override //解锁
  49. public void unlock() {
  50. sync.release(1);
  51. }
  52. @Override //创建条件变量
  53. public Condition newCondition() {
  54. return sync.newCondition();
  55. }
  56. }

P237 aqs 自定义锁 测试

  1. //自定义锁(不可重入锁)
  2. class MyLock implements Lock{
  3. //独占锁,同步器类
  4. class Mysync extends AbstractQueuedSynchronizer{
  5. @Override
  6. protected boolean tryAcquire(int arg) {
  7. if(compareAndSetState(0,1)){//其它线程可能也想修改状态
  8. //加上了锁,并设置owner为当前线程
  9. setExclusiveOwnerThread(Thread.currentThread());
  10. return true;
  11. }
  12. return false;
  13. }
  14. @Override
  15. protected boolean tryRelease(int arg) {
  16. setExclusiveOwnerThread(null);
  17. setState(0);
  18. return true;
  19. }
  20. @Override
  21. protected boolean isHeldExclusively() {
  22. return getState()==1;
  23. }
  24. public Condition newCondition(){
  25. return new ConditionObject();
  26. }
  27. }
  28. private Mysync sync = new Mysync();
  29. public MyLock() {
  30. super();
  31. }
  32. @Override //加锁,加锁不成功会放入队列等待
  33. public void lock() {
  34. sync.acquire(1);
  35. }
  36. @Override //加锁,可打断
  37. public void lockInterruptibly() throws InterruptedException {
  38. sync.acquireInterruptibly(1);
  39. }
  40. @Override //尝试加锁,只会尝试一次
  41. public boolean tryLock() {
  42. return sync.tryAcquire(1);
  43. }
  44. @Override //尝试加锁,带超时时间
  45. public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
  46. return sync.tryAcquireNanos(1,unit.toNanos(time));
  47. }
  48. @Override //解锁
  49. public void unlock() {
  50. sync.release(1);
  51. }
  52. @Override //创建条件变量
  53. public Condition newCondition() {
  54. return sync.newCondition();
  55. }
  56. }

P238 reentrantlock 加锁成功流程

P239 reentrantlock 枷锁失败流程

P240 reentrantlock 解锁竞争成功流程

下面是释放锁release的流程:

P241 reentrantlock 解锁竞争失败流程

P242 reentrantlock 锁重入原理

P243 reentrantlock 可打断原理

不可打断模式:即使被打断,仍会驻留在AQS队列中,等待获得锁后方能继续运行(是继续运行,只是打断标记被设为true)。

可打断模式:被打断之后直接抛出异常,不会再进入for循环。

P244 reentrantlock 公平锁原理

下图是非公平锁实现,任意节点都能竞争:

下图是公平锁实现,只有头节点的后一个节点能竞争:

P245 reentrantlock 条件变量 await

调用await,会进入addConditionWaiter流程,创建新的Node状态为-2

fullyRelease会把所有的锁都释放掉:

P246 reentrantlock 条件变量 signal

doSignal中transferForSignal返回true则转移成功,不会继续循环。如果转移失败的原因可能是线程放弃了对锁的竞争,因为超时等原因,就不会被加入队列。

waitStatus改为-1,表示它有责任去唤醒链表的下一个元素。

P247  reentrantreadwritelock 使用

ReentrantReadWriteLock支持重入的读写锁

当读操作远远高于写操作时,这时候要使用读写锁让读-读可以并发,提高性能。

但是写-写和读-写是互斥的。

加上读锁读取,隔了100毫秒后开始获取写锁,但是读休眠1秒,一秒后读锁释放,才能获取到写锁开始写入:

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) throws InterruptedException {
  4. DataContainer dataContainer = new DataContainer();
  5. new Thread(()->{
  6. dataContainer.read();
  7. },"t1").start();
  8. Thread.sleep(100);
  9. new Thread(()->{
  10. dataContainer.write();
  11. },"t1").start();
  12. }
  13. }
  14. @Slf4j(topic = "c.DataContainer")
  15. class DataContainer{
  16. private Object data;
  17. private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
  18. private ReentrantReadWriteLock.ReadLock r = rw.readLock();
  19. private ReentrantReadWriteLock.WriteLock w = rw.writeLock();
  20. public Object read(){
  21. log.debug("获取读锁...");
  22. r.lock();
  23. try {
  24. log.debug("读取");
  25. sleep(1);
  26. return data;
  27. } finally {
  28. log.debug("释放读锁");
  29. r.unlock();
  30. }
  31. }
  32. public void write(){
  33. log.debug("获取写锁...");
  34. w.lock();
  35. try {
  36. log.debug("写入");
  37. } finally {
  38. log.debug("释放写锁");
  39. w.unlock();
  40. }
  41. }
  42. }

P248 reentrantreadwritelock 注意事项

读锁不支持条件变量。

1.重入时不支持升级:比如:不允许持有读锁的情况下去获取写锁,会导致获取写锁永久等待。

2.重入时支持降级:比如:持有写锁的情况下去获取读锁。

一开始持有读锁,在获取写锁前要释放读锁。

写锁可以降级为读锁,最后再释放锁。

P249  reentrantreadwritelock 应用之缓存

 

P250  reentrantreadwritelock 应用之缓存 问题分析

先清缓存,再查数据库设置缓存值,如果后面有新数据写入数据库,缓存中一直是旧值。

要求先更新数据库再清空缓存:

P251  reentrantreadwritelock 应用之缓存 实现

加写锁,保证原子:

双重检查,先查缓存再查数据库:

P252  reentrantreadwritelock 应用之缓存 补充

P253  reentrantreadwritelock 原理 t1 w.lock

写锁状态占state的低16位,读锁使用的是state的高16位。

P254  reentrantreadwritelock 原理 t2 r.lock

P255  reentrantreadwritelock 原理 t3 r.lock & t4 w.lock

P256  reentrantreadwritelock 原理 t1 w.unlock

P257  reentrantreadwritelock 原理 t1 w.unlock

P258  reentrantreadwritelock 原理 t2 r.unlock t3 r.unlock

P259 stampedlock 作用

P260 stampedlock 演示

乐观读锁并没有加读锁,只是验证戳,只有当戳被更改过才会真正加读锁。可以提升并发读的性能。

缺点:不支持条件变量,不支持可重入。

P261 semaphore 作用

Semaphore是信号量,用来限制能同时访问共享资源的线程上限。

P262 semaphore 演示

  1. @Slf4j(topic = "c.Test1")
  2. public class Test1 {
  3. public static void main(String[] args) throws InterruptedException {
  4. Semaphore semaphore = new Semaphore(3);
  5. for (int i = 0; i < 10; i++) {
  6. new Thread(()->{
  7. try {
  8. semaphore.acquire();
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. try {
  13. log.debug("running...");
  14. sleep(1);
  15. log.debug("end...");
  16. }finally {
  17. semaphore.release();
  18. }
  19. }).start();
  20. }
  21. }
  22. }

限制访问共享资源的线程数: 

 

P263 semaphore 应用 改进数据库连接池

P264 semaphore 原理 acquire

P265 semaphore 原理 release

P266 countdownlatch 简介

P267 countdownlatch 改进

P268 countdownlatch 应用 等待多线程准备完毕

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/805269
推荐阅读
相关标签
  

闽ICP备14008679号