本文写给正在努力的自己,努力的补基础知识,五道题一篇
ps:我把答案都放在解析下面了
- socket编程中,一下哪个socket的操作不属于服务端操作()
A. accept
B. listen
C. connect
D. close
初识想法:socket(套接字),像是消息中间件的存在,存在于TCP/IP中
解析:在看这道题之前,我们想一下什么是TCP/IP,UDP?
那么他们存在于哪里呢?还记得OSI的七层模型吗?
分别是:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。那么我们来看看每层对应的协议吧
将它简化之后是四层模型,分别是:应用层,运输层,网络层,链路层,TCP/IP和UDP存在于运输层
那么TCP和UDP的区别我们简单来说:TCP比较负责会有三次握手和四次挥手,确保数据传输到,而UDP则不会,像是寄信,我只管寄出去,不管对方有没有收到
socket一词的起源
在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”
在java11的API中我们了解到socket类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通信的端点。
套接字的实际工作由SocketImpl类的实例执行。 通过更改创建套接字实现的套接字工厂,应用程序可以将自身配置为创建适合本地防火墙的套接字
在使用socket的时候常用的方法:
TCP客户端:
1.建立连接套接字,设置Ip和端口监听,socket()
2.建立连接 connect
3.write() 获取网络流对象 发送数据
4.read()获取网络流对象 接收数据
5.关闭套接字
TCP服务器端
1.建立端口监听 socket()
2.绑定指定端口 bind()
3.listen 进行端口监听
4.accept() 阻塞式 直到有客户端访问
5.read()获取客户端发送数据
6.write()发送返回数据
7.close关闭端口监听
答案:C
- 关于数据库连接的程序,以下哪个语句的注释是错误的( )
A. Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //指定MySQL JDBC驱动程序
B. String url=”jdbc:odbc:student_access”; //指定数据源为student_access
C. Connection con=DriverManager.getConnection(url); //创建连接指定数据库的对象
D. Statement stmt=con.creatStatement();//创建执行SQL语句的Statement对象
初识想法:框架用多了,这块已经忘了很多
解析:以下是我写的代码及注释
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.定义sql
String sql = "select * from kuaidi";
//3.获取conn
conn = DriverManager.getConnection("jdbc:mysql:///kuaidi", "root", "123");
//4.获取执行sql对象Statement
stmt = conn.createStatement();
//5.执行sql
rs = stmt.executeQuery(sql);
//6处理结果
while (rs.next()) {
int danhao = rs.getInt(1);
int qujianma = rs.getInt(2);
String gongsi = rs.getString("gongsi");
System.out.println(danhao + "===" + qujianma + gongsi);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
答案:A
- 关于volatile关键字,下列描述不正确的是?
A. 用volatile修饰的变量,每次更新对其他线程都是立即可见的
B. 对volatile变量的操作是原子性的。
C. 对volatile变量的操作不会造成阻塞。
D. 不依赖其他锁机制,多线程环境下的计数器可用volatile实现。
初识想法:忘了
解析:
转载于:http://www.ibm.com/developerworks/cn/Java/j-jtp06197.html
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。
锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。
Volatile 变量
Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。
出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。
正确使用 volatile 变量的条件
您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
对变量的写操作不依赖于当前值。
该变量没有包含在具有其他变量的不变式中。
实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。
第一个条件的限制使 volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使x 的值在操作期间保持不变,而 volatile 变量无法实现这点。(然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。)
大多数编程情形都会与这两个条件的其中之一冲突,使得 volatile 变量不能像 synchronized 那样普遍适用于实现线程安全。
答案:BD
- 以下说法错误的是()
A. 其他选项均不正确
B. java线程类优先级相同
C. Thread和Runnable接口没有区别
D. 如果一个类继承了某个类,只能使用Runnable实现线程
初识想法:java的线程调度方式是抢占调度是抢占式的,没有分等级,所以同时运行AB两个线程,会出现一会运行A,一会运行B,
解析:
B:我从JAVA11的API中找到
java 中的线程优先级的范围是1~10,默认的优先级是5,10极最高。
有时间片轮循机制。“高优先级线程”被分配CPU的概率高于“低优先级线程”。根据时间片轮循调度,所以能够并发执行。无论是是级别相同还是不同,线程调用都不会绝对按照优先级执行,每次执行结果都不一样,调度算法无规律可循,所以线程之间不能有先后依赖关系。
无时间片轮循机制时,高级别的线程优先执行,如果低级别的线程正在运行时,有高级别线程可运行状态,则会执行完低级别线程,再去执行高级别线程。如果低级别线程处于等待、睡眠、阻塞状态,或者调用yield()函数让当前运行线程回到可运行状态,以允许具有相同优先级或者高级别的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
我们通过代码带说明:
public class Demo4 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()
+ "(" + Thread.currentThread().getPriority() + ")");
Thread t1 = new ThreadP("thread1"); // 新建t1
Thread t2 = new ThreadP("thread2"); // 新建t2
t1.setPriority(5); // 设置t1的优先级为1
t2.setPriority(10); // 设置t2的优先级为10
t1.start(); // 启动t1
t2.start(); // 启动t2
}
}
class ThreadP extends Thread {
public ThreadP(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()
+ "(" + Thread.currentThread().getPriority() + ")"
+ ", loop " + i);
}
}
}
输出结果:
C: Thread实现了Runnable接口是一个类不是接口,错误
D:实现多线程的三种方式,一种是继承Thread类使用此方式就不能继承其他的类了。还有两种是实现Runnable接口或者实现Callable接口
,所以D错误。
答案:BCD
- 以下代码输出结果为?
public class Demo5 {
public static void main(String[] args) {
int i = 0;
Integer j = new Integer(0);
System.out.println(i == j);
System.out.println(j.equals(i));
}
}
初识想法:i是基本数据类型,j是引用类型
解析:由于==会触发CSDN的高光,所以用中文代替
1、基本型和基本型封装型进行"等等"运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;
2、两个Integer类型进行“等等”比较,如果其值在-128至127,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。
3、两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true
4、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较
答案:B