Java笔记(二)
10.
public | protected | default | private | |
同一个类中 | √ | √ | √ | √ |
同一个包中 | √ | √ | √ | |
子类 | √ | √ | ||
不同包中 | √ |
11. 线程:
static Thread currentThread():获取当前线程对象
getName():获取线程名称
设置线程名称:setName()或者构造函数
创建线程的方式:
1. 继承Thread类
(1)定义类,继承Thread
(2)复写Thread类中的void run()方法(因为Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。)
(3)调用线程的start方法,该方法能启动线程,并能调用run方法
注:对象.run()仅仅是对象调用方法。而线程创建了,并没有运行;
对象.start()开启线程并执行该线程的run方法
2. 实现Runnable接口
(1)定义类,实现Runnable接口
(2)覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中
(3)通过Thread类建立线程对象
(4)将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去执行指定对象的run方法,就必须明确该run方法所属的对象。
(5)调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法
实现方式与继承方式的区别:
实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。
继承Thread:线程代码存放在Thread子类run方法中;实现Runnable:线程代码存放在接口的子类的run方法。
同步函数的锁是this;静态同步函数的锁是Class对象(类名.class)
死锁:例:
- class DeadLock implements Runnable{
- private boolean flag;
- DeadLock(boolean flag){
- this.flag = flag;
- }
- public void run(){
- if(flag){
- while(true){
- synchronized(Lock.locka){
- System.out.println("if locka");
- synchronized(Lock.lockb){
- System.out.println("if lockb");
- }
- }
- }
- }
- else{
- while(true){
- synchronized(Lock.lockb){
- System.out.println("else lockb");
- synchronized(Lock.locka){
- System.out.println("else locka");
- }
- }
- }
- }
- }
- }
- class Lock{
- public static Object locka = new Object();
- public static Object lockb = new Object();
- }
- public class Demo{
- public static void main(String[] args) {
- Thread t1 = new Thread(new DeadLock(true));
- Thread t2 = new Thread(new DeadLock(false));
- t1.start();
- t2.start();
- }
- }
wait() notify() notifyAll():
都使用在同步中,因为要对持有监视器(锁)的线程操作,只有同步才具有锁。
这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁。只有同一个锁上的被等待线程,可以被同一个锁上的notify()唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被对象调用的方法定义Object类中。
生产者-消费者问题:
- class Resource{
- private String name;
- private int count = 1;
- private boolean flag = false;
- public synchronized void set(String name){
- while(flag){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- this.name = name + " ~~ " + count++;
- System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
- flag = true;
- this.notifyAll();
- }
- public synchronized void out(){
- while(!flag){
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
- flag = false;
- this.notifyAll();
- }
- }
- class Producer implements Runnable{
- private Resource r;
- Producer(Resource r){
- this.r = r;
- }
- public void run(){
- while(true){
- r.set("商品");
- }
- }
- }
- class Consumer implements Runnable{
- private Resource r;
- Consumer(Resource r){
- this.r = r;
- }
- public void run(){
- while(true){
- r.out();
- }
- }
- }
- public class Demo{
- public static void main(String[] args) {
- Resource r = new Resource();
- Thread t1 = new Thread(new Producer(r));
- Thread t2 = new Thread(new Producer(r));
- Thread t3 = new Thread(new Consumer(r));
- Thread t4 = new Thread(new Consumer(r));
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
对于多个生产者和消费者。定义while判断标记的原因:让被唤醒的线程再一次判断标记。
定义notifyAll的原因:需要唤醒对方线程。如果只用notify,容易 出现只唤醒本方线程的情况。导致程序中的所有线程都等待。
生产者-消费者(升级版):
- import java.util.concurrent.locks.Condition;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- class Resource{
- private String name;
- private int count = 1;
- private boolean flag = false;
- private Lock lock = new ReentrantLock();
- private Condition condition_pro = lock.newCondition();
- private Condition condition_con = lock.newCondition();
- public void set(String name) throws InterruptedException{
- lock.lock();
- try{
- while(flag){
- condition_pro.await();
- }
- this.name = name + " ~~ " + count++;
- System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
- flag = true;
- condition_con.signal();
- }finally{
- lock.unlock();
- }
- }
- public void out() throws InterruptedException{
- lock.lock();
- try{
- while(!flag){
- condition_con.await();
- }
- System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
- flag = false;
- condition_pro.signal();
- }finally{
- lock.unlock();
- }
- }
- }
- class Producer implements Runnable{
- private Resource r;
- Producer(Resource r){
- this.r = r;
- }
- public void run(){
- while(true){
- try {
- r.set("商品");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class Consumer implements Runnable{
- private Resource r;
- Consumer(Resource r){
- this.r = r;
- }
- public void run(){
- while(true){
- try {
- r.out();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- public class Demo{
- public static void main(String[] args) {
- Resource r = new Resource();
- Thread t1 = new Thread(new Producer(r));
- Thread t2 = new Thread(new Producer(r));
- Thread t3 = new Thread(new Consumer(r));
- Thread t4 = new Thread(new Consumer(r));
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
JDK1.5中提供了多线程升级解决方案。将同步Synchronized替换成Lock操作。将Object中的wait、notify、notifyAll替换成了Condition对象,该对象可以Lock锁进行获取。
如何停止线程:stop方法已经过时,只能让run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:当线程处于冻结状态。就不会读取到标记,那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法interrupt();
- class StopThread implements Runnable{
- private boolean flag = true;
- public synchronized void run(){
- while(flag){
- try{
- wait();
- }catch(InterruptedException e){
- System.out.println(Thread.currentThread().getName() + "...exception");
- }
- System.out.println(Thread.currentThread().getName() + "...run");
- }
- }
- public void changeFlag(){
- flag = false;
- }
- }
- public class Demo{
- public static void main(String[] args) {
- StopThread st = new StopThread();
- Thread t1 = new Thread(st);
- Thread t2 = new Thread(st);
- t1.start();
- t2.start();
- int num = 0;
- while(true){
- if(num++ == 60){
- t1.interrupt();
- t2.interrupt();
- st.changeFlag();
- break;
- }
- System.out.println(Thread.currentThread().getName() + "....." + num);
- }
- System.out.println("over");
- }
- }
输出结果:
- ...
- ...
- main.....59
- main.....60
- over
- Thread-0...exception
- Thread-0...run
- Thread-1...exception
- Thread-1...run
守护线程:即后台线程。线程对象.setDaemon(true)
当正在运行的线程都是守护线程时(即前台线程全结束),JVM退出。该方法必须在启动线程前调用。
Join方法:线程对象.join(),当A线程执行到了B线程的.join()方法,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。
yield方法:暂停当前正在执行的线程对象,并执行其他线程。
Java笔记(二)的更多相关文章
- Java笔记(二十九)……网络编程
概述 网络模型 网络通讯的要素 ip地址:网络中设备的标识符 端口:用于标识同一台设备上不同的进程,有效端口:0~65535,其中0~1024是系统使用端口或者保留端口 TCP与UDP UDP特点: ...
- Java笔记(二十八)……IO流下 IO包中其他常用类以及编码表问题
PrintWriter打印流 Writer的子类,既可以接收字符流,也可以接收字节流,还可以接收文件名或者文件对象,非常方便 同时,还可以设置自动刷新以及保持原有格式写入各种文本类型的print方法 ...
- Java笔记(二十七)……IO流中 File文件对象与Properties类
File类 用来将文件或目录封装成对象 方便对文件或目录信息进行处理 File对象可以作为参数传递给流进行操作 File类常用方法 创建 booleancreateNewFile():创建新文件,如果 ...
- Java笔记(二十六)……IO流上 字节流与字符流
概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...
- Java笔记(二十五)……其他常用API
System类 工具类全部都是静态方法 常用方法 获取系统属性信息 static PropertiesgetProperties() static StringgetProperty(String k ...
- Java笔记(二十四)……集合工具类Collections&Arrays
Collections 集合框架的工具类,方法全部为静态 Collections与Collection的区别 Collection是集合框架的一个顶层接口,里面定义了单列集合的共性方法 Collect ...
- Java笔记(二十三)……Map集合
Map接口 Map<K,V> 该集合存储的是键值对,成对往集合里存,而且要保证键的唯一性 常用方法 添加 Vput(K key, V value) voidputAll(Map<? ...
- Java笔记(二十二)……Collection集合
概述 为什么会出现集合类 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式 数组和集合类同是容器,有何不同 数组虽然也可以存储 ...
- Java笔记(二十)……线程间通信
概述 当需要多线程配合完成一项任务时,往往需要用到线程间通信,以确保任务的稳步快速运行 相关语句 wait():挂起线程,释放锁,相当于自动放弃了执行权限 notify():唤醒wait等待队列里的第 ...
- Java笔记(二)……Hello world!
编写源文件 将Java代码编写到扩展名为.java的文件中,此文件称为源文件. 1: class Hello 2: { 3: public static void main(String[] args ...
随机推荐
- WinForm 子窗体在父窗体范围内移动,不能出父窗体 摘自于网络
详细解释:1, 主窗体Form1属性IsMdiContainer设为True,并添加ToolStrip控件, Toolstrip中添加一个按钮toolStripButton1. 2,添 ...
- 旋转图css3
<!doctype html><html> <head> <meta charset="UTF-8"> <title> ...
- javaweb 国际化
国际化又称为 i18n:internationalization 软件实现国际化,需具备哪些特征:对于程序中固定使用的文本元素,例如菜单栏.导航条等中使用的文本元素.或错误提示信息,状态信息等,需要根 ...
- 包(package)
防止文件重名,包体现在文件夹上.包必须建立文件夹. 类名的全称是:包名.类名 javac xx.java 命令编译的时候,不会建立对应的文件夹, 建立包对应的文件夹的命令,要用 javac -d ...
- Newly Setting up a CentOS-7 system
yum install -y epel-release glibc.i686 libtools vim clang git autoconf automake w3m glibc screen the ...
- UIImage+Scale
Scale a UIImage to any given rect keeping the aspect ratio Raw UIImage+Scale.m @implementation UI ...
- HDU 5833 (2016大学生网络预选赛) Zhu and 772002(高斯消元求齐次方程的秩)
网络预选赛的题目……比赛的时候没有做上,确实是没啥思路,只知道肯定是整数分解,然后乘起来素数的幂肯定是偶数,然后就不知道该怎么办了… 最后题目要求输出方案数,首先根据题目应该能写出如下齐次方程(从别人 ...
- UIImage 和 UIImageView区别
// // ViewController.m // 06-UIImage 和 UIImageView // // Created by Stephen on 16/4/18. // Copyright ...
- 关于:hover的一点小问题
今天又用到了:hover这个伪类选择器,一个小问题搞了我好久,就是关于:hover选择的问题, 先看下css代码 .box:hover span { height: 150px; } 接下来是HTML ...
- 转:Jmeter常见问题 (转载) http://www.51testing.com/?uid-128005-action-viewspace-itemid-84094
说明:这些问答是从网上转载的,自己修改了其中的一些内容,如果大家兴趣,可以将大家在使用Jmeter的时候碰到的问题写下来,我们一起补充到这个问答里面,共同努力完善jmeter的资料. 1. JMet ...