java线程笔记

线程基础

线程使用方式

有三种使用线程的方法:

  • 实现 Runnable 接口;
  • 实现 Callable 接口;
  • 继承 Thread 类。

实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以说任务是通过线程驱动从而执行的。

实现 Runnable 接口

需要实现 run() 方法。

通过 Thread 调用 start() 方法来启动线程。

public static void main(String[] args) {
    MyRunnable instance = new MyRunnable();
    Thread thread = new Thread(instance);
    thread.start();
}

实现 Callable 接口

与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。

public static void main(String[] args) throws ExecutionException, InterruptedException {
    MyCallable mc = new MyCallable();
    FutureTask<String> ft = new FutureTask<>(mc);
    Thread thread = new Thread(ft);
    thread.start();
    System.out.println(ft.get());
}

继承 Thread 类

同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。

当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。

public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
}

实现接口 VS 继承 Thread

实现接口会更好一些,因为:

  • Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
  • 类可能只要求可执行就行,继承整个 Thread 类开销过大。

基础线程机制

Executor

Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。

主要有三种 Executor:

  • CachedThreadPool: 一个任务创建一个线程;
  • FixedThreadPool: 所有任务只能使用固定大小的线程;
  • SingleThreadExecutor: 相当于大小为 1 的 FixedThreadPool。
public static void main(String[] args) {
    ExecutorService executorService = Executors.newCachedThreadPool();
    // ExecutorService executorService = Executors.newFixedThreadPool(5);
    // ExecutorService executorService = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 5; i++) {
        executorService.execute(new MyRunnable());
    }
    executorService.shutdown();
}

Daemon

守护线程是程序运行时在后台提供服务的线程,不属于程序中不可或缺的部分。

当所有非守护线程结束时,程序也就终止,同时会杀死所有守护线程。

守护线程的作用及应用场景:通常来说,守护线程经常被用来执行一些后台任务,但是呢,你又希望在程序退出时, 或者说 JVM 退出时,线程能够自动关闭,此时,守护线程是你的首选。

main() 属于非守护线程。

使用 setDaemon() 方法将一个线程设置为守护线程。

public static void main(String[] args) {
    Thread thread = new Thread(new MyRunnable());
    thread.setDaemon(true);
}

sleep()

Thread.sleep(millisec) 方法会休眠当前正在执行的线程,millisec 单位为毫秒。

sleep() 可能会抛出 InterruptedException,因为异常不能跨线程传播回 main() 中,因此必须在本地进行处理。线程中抛出的其它异常也同样需要在本地进行处理。

class MyRunnable implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("启动线程");
            Thread.sleep(3000);
            System.out.println("阻塞3秒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

yield()

对静态方法 Thread.yield() 的调用声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行。该方法只是对线程调度器的一个建议,而且也只是建议具有相同优先级的其它线程可以运行。

class MyRunnable implements Runnable {
    @Override
  	public void run() {
    	Thread.yield();
	}
}

一、grep 详解

awk,sed,grep 是linux中最为常用的三大文本处理工具。
简单记录grep命令:
常用格式为:grep [option] PATTERN file grep [选项] “模式” [文件]
grep家族总共有三个:grep,egrep,fgrep。
示例:
cat filename | grep -v "#" |grep -v "^$" > temp.txt
查看文件,过滤注释行,过滤空行,重定向写入到新文件

常用选项:

-E :开启扩展(Extend)的正则表达式,也就相当于使用egrep。 或操作

-F :   解释PATTERN作为固定字符串的列表,由换行符分隔,其中任何一个都要匹配。也就相当于使用fgrep。

-G:   将范本样式视为普通的表示法来使用。这是默认值。加不加都是使用grep。

匹配控制选项:

-e :  使用PATTERN作为模式。这可以用于指定多个搜索模式,或保护以连字符( - )开头的图案。指定字符串做为查找文件内容的样式。 

-f :  指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。

-i :忽略大小写(ignore case)。

-v :反过来(invert),选择没有被匹配到的内容。

-w :匹配整词,精确地单词,单词的两边必须是非字符符号,被匹配的文本只能是单词,而不能是单词中的某一部分。

-x:仅选择与整行完全匹配的匹配项。精确匹配整行内容(包括行首行尾那些看不到的空格内容都要完全匹配)

-y:此参数的效果和指定“-i”参数相同。

一般输出控制选项:

-c :显示总共有多少行被匹配到了,而不是显示被匹配到的内容,注意如果同时使用-cv选项是显示有多少行没有被匹配到。

--color [= WHEN]:将匹配到的内容以颜色高亮显示。如 --color = auto

-L:列出文件内容不符合指定的范本样式的文件名称

-l : 列出文件内容符合指定的范本样式的文件名称。

-m num:当匹配内容的行数达到num行后,grep停止搜索,并输出停止前搜索到的匹配内容

-o :只显示被模式匹配到的字符串,匹配行中其他内容不会输出。

-q:安静模式,不会有任何输出内容,查找到匹配内容会返回0,未查找到匹配内容就返回非0

-s:不会输出查找过程中出现的任何错误消息。
-q和-s选项因为与其他系统的grep有兼容问题,shell脚本应该避免使用-q和-s,并且应该将标准和错误输出重定向到/dev/null 代替。

输出线前缀控制:

-b:输出每一个匹配行(或匹配的字符串)时在其前附加上偏移量(从文件第一个字符到该匹配内容之间的字节数)

-H:在每一个匹配行之前加上文件名一起输出(针对于查找单个文件),当查找多个文件时默认就会输出文件名

-h:禁止输出上的文件名的前缀。无论查找几个文件都不会在匹配内容前输出文件名

--label = LABEL:显示实际来自标准输入的输入作为来自文件LABEL的输入。这是特别在实现zgrep等工具时非常有用,例如gzip -cd foo.gz | grep --label = foo -H的东西。看到 也是-H选项。

-n:输出匹配内容的同时输出其所在行号。

-T:初始标签确保实际行内容的第一个字符位于制表位上,以便对齐标签看起来很正常。在匹配信息和其前的附加信息之间加入tab以使格式整齐。

上下文线控制选项:

-A num:匹配到搜索到的行以及该行下面的num行

-B num:匹配到搜索到的行以及该行上面的num行

-C num:匹配到搜索到的行以及上下各num行

文件和目录选择选项:

-a: 处理二进制文件,就像它是文本;这相当于--binary-files = text选项。不忽略二进制的数据。  

 --binary-files = TYPE:如果文件的前几个字节指示文件包含二进制数据,则假定该文件为类型TYPE。默认情况下,TYPE是二进制的,grep通常输出一行消息二进制文件匹配,或者如果没有匹配则没有消息。如果TYPE不匹配,grep假定二进制文件不匹配;这相当于-I选项。如果TYPE是文本,则grep处理a二进制文件,如果它是文本;这相当于-a选项。警告:grep --binary-files = text可能会输出二进制的垃圾,如果输出是一个终端和如果可能有讨厌的副作用终端驱动程序将其中的一些解释为命令。

-D:如果输入文件是设备,FIFO或套接字,请使用ACTION处理。默认情况下,读取ACTION,这意味着设备被读取,就像它们是普通文件一样。如果跳过ACTION,设备为 默默地跳过。

-d:  如果输入文件是目录,请使用ACTION处理它。默认情况下,ACTION是读的,这意味着目录被读取,就像它们是普通文件一样。如果跳过ACTION,目录将静默跳过。如果ACTION是recurse,grep将递归读取每个目录下的所有文件;这是相当于-r选项。

--exclude=GLOB:跳过基本名称与GLOB匹配的文件(使用通配符匹配)。文件名glob可以使用*,?和[...]作为通配符,和\引用通配符或反斜杠字符。搜索其文件名和GLOB通配符相匹配的文件的内容来查找匹配使用方法:grep -H --exclude=c* "old" ./*  c*是通配文件名的通配符./* 指定需要先通配文件名的文件的范围,必须要给*,不然就匹配不出内容,(如果不给*,带上-r选项也可以匹配)

--exclude-from = FILE:在文件中编写通配方案,grep将不会到匹配方案中文件名的文件去查找匹配内容

--exclude-dir = DIR:匹配一个目录下的很多内容同时还要让一些子目录不接受匹配,就使用此选项。

 --include = GLOB:仅搜索其基本名称与GLOB匹配的文件(使用--exclude下所述的通配符匹配)。

-R ,-r :以递归方式读取每个目录下的所有文件; 这相当于-d recurse选项。

其他选项:

--line-buffered: 在输出上使用行缓冲。这可能会导致性能损失。

--mmap:启用mmap系统调用代替read系统调用

-U:将文件视为二进制。

-z:将输入视为一组行,每一行由一个零字节(ASCII NUL字符)而不是a终止新队。与-Z或--null选项一样,此选项可以与排序-z等命令一起使用来处理任意文件名。
-n :显示行号



-A  n:显示匹配到的字符串所在的行及其后n行,after

-B  n:显示匹配到的字符串所在的行及其前n行,before

-C  n:显示匹配到的字符串所在的行及其前后各n行,context

grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。

grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。

你可能感兴趣的:(Java,java,笔记,开发语言)